--- a/.hgtags Mon Sep 14 07:02:50 2015 +0200
+++ b/.hgtags Mon Sep 14 07:03:04 2015 +0000
@@ -322,3 +322,4 @@
c25e882cee9622ec75c4e9d60633539a2f0a8809 jdk9-b77
c8753d0be1778944dc512ec86a459941ea1ad2c3 jdk9-b78
3966bd3b8167419aa05c6718a4af1cf54b1e3c58 jdk9-b79
+3c9f5bd909ae7187f24622ee4b69f8a5756a9271 jdk9-b80
--- a/.hgtags-top-repo Mon Sep 14 07:02:50 2015 +0200
+++ b/.hgtags-top-repo Mon Sep 14 07:03:04 2015 +0000
@@ -322,3 +322,4 @@
7972dc8f2a47f0c4cd8f02fa5662af41f028aa14 jdk9-b77
8c40d4143ee13bdf8170c68cc384c36ab1e9fadb jdk9-b78
ba08a9f79b9849716bae1f39f71333d47f604012 jdk9-b79
+f7c5ae2933c0b8510a420d1713a955e4ffc7ad0b jdk9-b80
--- a/common/bin/logger.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/common/bin/logger.sh Mon Sep 14 07:03:04 2015 +0000
@@ -41,5 +41,19 @@
trap "rm -rf \"$RCDIR\"" EXIT
LOGFILE=$1
shift
+
+# We need to handle command likes like "VAR1=val1 /usr/bin/cmd VAR2=val2".
+# Do this by shifting away prepended variable assignments, and export them
+# instead.
+is_prefix=true
+for opt; do
+ if [[ "$is_prefix" = true && "$opt" =~ ^.*=.*$ ]]; then
+ export $opt
+ shift
+ else
+ is_prefix=false
+ fi
+done
+
(exec 3>&1 ; ("$@" 2>&1 1>&3; echo $? > "$RCDIR/rc") | tee -a $LOGFILE 1>&2 ; exec 3>&-) | tee -a $LOGFILE
exit `cat "$RCDIR/rc"`
--- a/corba/.hgtags Mon Sep 14 07:02:50 2015 +0200
+++ b/corba/.hgtags Mon Sep 14 07:03:04 2015 +0000
@@ -322,3 +322,4 @@
8bb2441c0fec8b28f7bf11a0ca3ec1642e7ef457 jdk9-b77
182bb7accc5253bcfefd8edc1d4997ec8f9f8694 jdk9-b78
4ab250b8fac66ef8cd15ee78c40f0c651c96e16a jdk9-b79
+821a0373ef2d1642a9824facb938b901ad010413 jdk9-b80
--- a/hotspot/.hgtags Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/.hgtags Mon Sep 14 07:03:04 2015 +0000
@@ -482,3 +482,4 @@
e66c3813789debfc06f206afde1bf7a84cb08451 jdk9-b77
20dc06b04fe5ec373879414d60ef82ac70faef98 jdk9-b78
e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79
+8e8377739c06b99b9011c003c77e0bef84c91e09 jdk9-b80
--- a/hotspot/make/Makefile Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/Makefile Mon Sep 14 07:03:04 2015 +0000
@@ -633,9 +633,9 @@
update_jdk: export_product_jdk export_fastdebug_jdk test_jdk
-copy_jdk: $(JDK_IMAGE_DIR)/jre/lib/rt.jar
+copy_jdk: $(JDK_IMAGE_DIR)/bin/java
-$(JDK_IMAGE_DIR)/jre/lib/rt.jar:
+$(JDK_IMAGE_DIR)/bin/java:
$(RM) -r $(JDK_IMAGE_DIR)
$(MKDIR) -p $(JDK_IMAGE_DIR)
($(CD) $(JDK_IMPORT_PATH) && \
--- a/hotspot/make/aix/makefiles/mapfile-vers-debug Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/aix/makefiles/mapfile-vers-debug Mon Sep 14 07:03:04 2015 +0000
@@ -141,18 +141,6 @@
JVM_Halt;
JVM_HoldsLock;
JVM_IHashCode;
- JVM_ImageAttributeOffsets;
- JVM_ImageAttributeOffsetsLength;
- JVM_ImageClose;
- JVM_ImageFindAttributes;
- JVM_ImageGetAttributes;
- JVM_ImageGetAttributesCount;
- JVM_ImageGetDataAddress;
- JVM_ImageGetIndexAddress;
- JVM_ImageGetStringBytes;
- JVM_ImageOpen;
- JVM_ImageRead;
- JVM_ImageReadCompressed;
JVM_InitAgentProperties;
JVM_InitProperties;
JVM_InternString;
--- a/hotspot/make/aix/makefiles/mapfile-vers-product Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/aix/makefiles/mapfile-vers-product Mon Sep 14 07:03:04 2015 +0000
@@ -139,18 +139,6 @@
JVM_Halt;
JVM_HoldsLock;
JVM_IHashCode;
- JVM_ImageAttributeOffsets;
- JVM_ImageAttributeOffsetsLength;
- JVM_ImageClose;
- JVM_ImageFindAttributes;
- JVM_ImageGetAttributes;
- JVM_ImageGetAttributesCount;
- JVM_ImageGetDataAddress;
- JVM_ImageGetIndexAddress;
- JVM_ImageGetStringBytes;
- JVM_ImageOpen;
- JVM_ImageRead;
- JVM_ImageReadCompressed;
JVM_InitAgentProperties;
JVM_InitProperties;
JVM_InternString;
--- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug Mon Sep 14 07:03:04 2015 +0000
@@ -139,18 +139,6 @@
_JVM_Halt
_JVM_HoldsLock
_JVM_IHashCode
- _JVM_ImageAttributeOffsets
- _JVM_ImageAttributeOffsetsLength
- _JVM_ImageClose
- _JVM_ImageFindAttributes
- _JVM_ImageGetAttributes
- _JVM_ImageGetAttributesCount
- _JVM_ImageGetDataAddress
- _JVM_ImageGetIndexAddress
- _JVM_ImageGetStringBytes
- _JVM_ImageOpen
- _JVM_ImageRead
- _JVM_ImageReadCompressed
_JVM_InitAgentProperties
_JVM_InitProperties
_JVM_InternString
--- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product Mon Sep 14 07:03:04 2015 +0000
@@ -139,18 +139,6 @@
_JVM_Halt
_JVM_HoldsLock
_JVM_IHashCode
- _JVM_ImageAttributeOffsets
- _JVM_ImageAttributeOffsetsLength
- _JVM_ImageClose
- _JVM_ImageFindAttributes
- _JVM_ImageGetAttributes
- _JVM_ImageGetAttributesCount
- _JVM_ImageGetDataAddress
- _JVM_ImageGetIndexAddress
- _JVM_ImageGetStringBytes
- _JVM_ImageOpen
- _JVM_ImageRead
- _JVM_ImageReadCompressed
_JVM_InitAgentProperties
_JVM_InitProperties
_JVM_InternString
--- a/hotspot/make/bsd/makefiles/mapfile-vers-debug Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug Mon Sep 14 07:03:04 2015 +0000
@@ -141,18 +141,6 @@
JVM_Halt;
JVM_HoldsLock;
JVM_IHashCode;
- JVM_ImageAttributeOffsets;
- JVM_ImageAttributeOffsetsLength;
- JVM_ImageClose;
- JVM_ImageFindAttributes;
- JVM_ImageGetAttributes;
- JVM_ImageGetAttributesCount;
- JVM_ImageGetDataAddress;
- JVM_ImageGetIndexAddress;
- JVM_ImageGetStringBytes;
- JVM_ImageOpen;
- JVM_ImageRead;
- JVM_ImageReadCompressed;
JVM_InitAgentProperties;
JVM_InitProperties;
JVM_InternString;
--- a/hotspot/make/bsd/makefiles/mapfile-vers-product Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-product Mon Sep 14 07:03:04 2015 +0000
@@ -141,18 +141,6 @@
JVM_Halt;
JVM_HoldsLock;
JVM_IHashCode;
- JVM_ImageAttributeOffsets;
- JVM_ImageAttributeOffsetsLength;
- JVM_ImageClose;
- JVM_ImageFindAttributes;
- JVM_ImageGetAttributes;
- JVM_ImageGetAttributesCount;
- JVM_ImageGetDataAddress;
- JVM_ImageGetIndexAddress;
- JVM_ImageGetStringBytes;
- JVM_ImageOpen;
- JVM_ImageRead;
- JVM_ImageReadCompressed;
JVM_InitAgentProperties;
JVM_InitProperties;
JVM_InternString;
--- a/hotspot/make/bsd/makefiles/vm.make Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/bsd/makefiles/vm.make Mon Sep 14 07:03:04 2015 +0000
@@ -131,7 +131,7 @@
# By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM
-JDK_LIBDIR = $(JAVA_HOME)/jre/lib/$(LIBARCH)
+JDK_LIBDIR = $(JAVA_HOME)/lib/$(LIBARCH)
#----------------------------------------------------------------------
# jvm_db & dtrace
--- a/hotspot/make/build.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/build.sh Mon Sep 14 07:03:04 2015 +0000
@@ -49,7 +49,7 @@
# Just in case:
JAVA_HOME=`( cd $JAVA_HOME; pwd )`
-if [ "${ALT_BOOTDIR-}" = "" -o ! -d "${ALT_BOOTDIR-}" -o ! -d ${ALT_BOOTDIR-}/jre/lib/ ]; then
+if [ "${ALT_BOOTDIR-}" = "" -o ! -d "${ALT_BOOTDIR-}" -o ! -d ${ALT_BOOTDIR-}/lib/ ]; then
ALT_BOOTDIR=${JAVA_HOME}
fi
--- a/hotspot/make/hotspot.script Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/hotspot.script Mon Sep 14 07:03:04 2015 +0000
@@ -127,7 +127,7 @@
# o $JRE/lib/$ARCH
# followed by the user's previous effective LD_LIBRARY_PATH, if
# any.
-JRE=$JDK/jre
+JRE=$JDK
JAVA_HOME=$JDK
export JAVA_HOME
--- a/hotspot/make/linux/makefiles/mapfile-vers-debug Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/linux/makefiles/mapfile-vers-debug Mon Sep 14 07:03:04 2015 +0000
@@ -141,18 +141,6 @@
JVM_Halt;
JVM_HoldsLock;
JVM_IHashCode;
- JVM_ImageAttributeOffsets;
- JVM_ImageAttributeOffsetsLength;
- JVM_ImageClose;
- JVM_ImageFindAttributes;
- JVM_ImageGetAttributes;
- JVM_ImageGetAttributesCount;
- JVM_ImageGetDataAddress;
- JVM_ImageGetIndexAddress;
- JVM_ImageGetStringBytes;
- JVM_ImageOpen;
- JVM_ImageRead;
- JVM_ImageReadCompressed;
JVM_InitAgentProperties;
JVM_InitProperties;
JVM_InternString;
--- a/hotspot/make/linux/makefiles/mapfile-vers-product Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/linux/makefiles/mapfile-vers-product Mon Sep 14 07:03:04 2015 +0000
@@ -141,18 +141,6 @@
JVM_Halt;
JVM_HoldsLock;
JVM_IHashCode;
- JVM_ImageAttributeOffsets;
- JVM_ImageAttributeOffsetsLength;
- JVM_ImageClose;
- JVM_ImageFindAttributes;
- JVM_ImageGetAttributes;
- JVM_ImageGetAttributesCount;
- JVM_ImageGetDataAddress;
- JVM_ImageGetIndexAddress;
- JVM_ImageGetStringBytes;
- JVM_ImageOpen;
- JVM_ImageRead;
- JVM_ImageReadCompressed;
JVM_InitAgentProperties;
JVM_InitProperties;
JVM_InternString;
--- a/hotspot/make/solaris/makefiles/adlc.make Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/solaris/makefiles/adlc.make Mon Sep 14 07:03:04 2015 +0000
@@ -76,6 +76,11 @@
ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1)
CFLAGS_WARN = +w -errwarn
endif
+# When using compiler version 5.13 (Solaris Studio 12.4), calls to explicitly
+# instantiated template functions trigger this warning when +w is active.
+ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 513), 1)
+ CFLAGS_WARN += -erroff=notemsource
+endif
CFLAGS += $(CFLAGS_WARN)
ifeq ("${Platform_compiler}", "sparcWorks")
--- a/hotspot/make/solaris/makefiles/buildtree.make Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/solaris/makefiles/buildtree.make Mon Sep 14 07:03:04 2015 +0000
@@ -270,6 +270,7 @@
echo "CP ?= cp"; \
echo "MV ?= mv"; \
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
+ echo "include \$$(GAMMADIR)/make/excludeSrc.make"; \
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
) > $@
--- a/hotspot/make/solaris/makefiles/mapfile-vers Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/solaris/makefiles/mapfile-vers Mon Sep 14 07:03:04 2015 +0000
@@ -141,18 +141,6 @@
JVM_Halt;
JVM_HoldsLock;
JVM_IHashCode;
- JVM_ImageAttributeOffsets;
- JVM_ImageAttributeOffsetsLength;
- JVM_ImageClose;
- JVM_ImageFindAttributes;
- JVM_ImageGetAttributes;
- JVM_ImageGetAttributesCount;
- JVM_ImageGetDataAddress;
- JVM_ImageGetIndexAddress;
- JVM_ImageGetStringBytes;
- JVM_ImageOpen;
- JVM_ImageRead;
- JVM_ImageReadCompressed;
JVM_InitAgentProperties;
JVM_InitProperties;
JVM_InternString;
--- a/hotspot/make/solaris/makefiles/vm.make Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/make/solaris/makefiles/vm.make Mon Sep 14 07:03:04 2015 +0000
@@ -197,7 +197,7 @@
Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS)
Src_Dirs/TIERED := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS)
Src_Dirs/ZERO := $(CORE_PATHS)
-Src_Dirs/SHARK := $(CORE_PATHS)
+Src_Dirs/SHARK := $(CORE_PATHS) $(SHARK_PATHS)
Src_Dirs := $(Src_Dirs/$(TYPE))
COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\*
@@ -206,7 +206,7 @@
ZERO_SPECIFIC_FILES := zero
# Always exclude these.
-Src_Files_EXCLUDE := dtrace jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
+Src_Files_EXCLUDE += dtrace jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
# Exclude per type.
Src_Files_EXCLUDE/CORE := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Sep 14 07:03:04 2015 +0000
@@ -3803,81 +3803,37 @@
enc_class aarch64_enc_cmpxchg(memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{
MacroAssembler _masm(&cbuf);
- Register old_reg = as_Register($oldval$$reg);
- Register new_reg = as_Register($newval$$reg);
- Register base = as_Register($mem$$base);
- Register addr_reg;
- int index = $mem$$index;
- int scale = $mem$$scale;
- int disp = $mem$$disp;
- if (index == -1) {
- if (disp != 0) {
- __ lea(rscratch2, Address(base, disp));
- addr_reg = rscratch2;
- } else {
- // TODO
- // should we ever get anything other than this case?
- addr_reg = base;
- }
- } else {
- Register index_reg = as_Register(index);
- if (disp == 0) {
- __ lea(rscratch2, Address(base, index_reg, Address::lsl(scale)));
- addr_reg = rscratch2;
- } else {
- __ lea(rscratch2, Address(base, disp));
- __ lea(rscratch2, Address(rscratch2, index_reg, Address::lsl(scale)));
- addr_reg = rscratch2;
- }
- }
- Label retry_load, done;
- __ bind(retry_load);
- __ ldxr(rscratch1, addr_reg);
- __ cmp(rscratch1, old_reg);
- __ br(Assembler::NE, done);
- __ stlxr(rscratch1, new_reg, addr_reg);
- __ cbnzw(rscratch1, retry_load);
- __ bind(done);
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
+ &Assembler::ldxr, &MacroAssembler::cmp, &Assembler::stlxr);
%}
enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
- Register old_reg = as_Register($oldval$$reg);
- Register new_reg = as_Register($newval$$reg);
- Register base = as_Register($mem$$base);
- Register addr_reg;
- int index = $mem$$index;
- int scale = $mem$$scale;
- int disp = $mem$$disp;
- if (index == -1) {
- if (disp != 0) {
- __ lea(rscratch2, Address(base, disp));
- addr_reg = rscratch2;
- } else {
- // TODO
- // should we ever get anything other than this case?
- addr_reg = base;
- }
- } else {
- Register index_reg = as_Register(index);
- if (disp == 0) {
- __ lea(rscratch2, Address(base, index_reg, Address::lsl(scale)));
- addr_reg = rscratch2;
- } else {
- __ lea(rscratch2, Address(base, disp));
- __ lea(rscratch2, Address(rscratch2, index_reg, Address::lsl(scale)));
- addr_reg = rscratch2;
- }
- }
- Label retry_load, done;
- __ bind(retry_load);
- __ ldxrw(rscratch1, addr_reg);
- __ cmpw(rscratch1, old_reg);
- __ br(Assembler::NE, done);
- __ stlxrw(rscratch1, new_reg, addr_reg);
- __ cbnzw(rscratch1, retry_load);
- __ bind(done);
- %}
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
+ &Assembler::ldxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
+ %}
+
+
+ // The only difference between aarch64_enc_cmpxchg and
+ // aarch64_enc_cmpxchg_acq is that we use load-acquire in the
+ // CompareAndSwap sequence to serve as a barrier on acquiring a
+ // lock.
+ enc_class aarch64_enc_cmpxchg_acq(memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{
+ MacroAssembler _masm(&cbuf);
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
+ &Assembler::ldaxr, &MacroAssembler::cmp, &Assembler::stlxr);
+ %}
+
+ enc_class aarch64_enc_cmpxchgw_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
+ MacroAssembler _masm(&cbuf);
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
+ &Assembler::ldaxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
+ %}
+
// auxiliary used for CompareAndSwapX to set result register
enc_class aarch64_enc_cset_eq(iRegINoSp res) %{
@@ -4373,12 +4329,12 @@
return;
}
- if (UseBiasedLocking) {
- __ biased_locking_enter(disp_hdr, oop, box, tmp, true, cont);
+ if (UseBiasedLocking && !UseOptoBiasInlining) {
+ __ biased_locking_enter(box, oop, disp_hdr, tmp, true, cont);
}
// Handle existing monitor
- if (EmitSync & 0x02) {
+ if ((EmitSync & 0x02) == 0) {
// we can use AArch64's bit test and branch here but
// markoopDesc does not define a bit index just the bit value
// so assert in case the bit pos changes
@@ -4398,13 +4354,10 @@
// Compare object markOop with mark and if equal exchange scratch1
// with object markOop.
- // Note that this is simply a CAS: it does not generate any
- // barriers. These are separately generated by
- // membar_acquire_lock().
{
Label retry_load;
__ bind(retry_load);
- __ ldxr(tmp, oop);
+ __ ldaxr(tmp, oop);
__ cmp(tmp, disp_hdr);
__ br(Assembler::NE, cas_failed);
// use stlxr to ensure update is immediately visible
@@ -4454,7 +4407,7 @@
{
Label retry_load, fail;
__ bind(retry_load);
- __ ldxr(rscratch1, tmp);
+ __ ldaxr(rscratch1, tmp);
__ cmp(disp_hdr, rscratch1);
__ br(Assembler::NE, fail);
// use stlxr to ensure update is immediately visible
@@ -4518,7 +4471,7 @@
return;
}
- if (UseBiasedLocking) {
+ if (UseBiasedLocking && !UseOptoBiasInlining) {
__ biased_locking_exit(oop, tmp, cont);
}
@@ -8017,10 +7970,10 @@
match(MemBarAcquireLock);
ins_cost(VOLATILE_REF_COST);
- format %{ "membar_acquire_lock" %}
-
- ins_encode %{
- __ membar(Assembler::LoadLoad|Assembler::LoadStore);
+ format %{ "membar_acquire_lock (elided)" %}
+
+ ins_encode %{
+ __ block_comment("membar_acquire_lock (elided)");
%}
ins_pipe(pipe_serial);
@@ -8080,10 +8033,10 @@
match(MemBarReleaseLock);
ins_cost(VOLATILE_REF_COST);
- format %{ "membar_release_lock" %}
-
- ins_encode %{
- __ membar(Assembler::LoadStore|Assembler::StoreStore);
+ format %{ "membar_release_lock (elided)" %}
+
+ ins_encode %{
+ __ block_comment("membar_release_lock (elided)");
%}
ins_pipe(pipe_serial);
@@ -8369,7 +8322,11 @@
ins_pipe(pipe_serial);
%}
-// this has to be implemented as a CAS
+
+// storeLConditional is used by PhaseMacroExpand::expand_lock_node
+// when attempting to rebias a lock towards the current thread. We
+// must use the acquire form of cmpxchg in order to guarantee acquire
+// semantics in this case.
instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr)
%{
match(Set cr (StoreLConditional mem (Binary oldval newval)));
@@ -8381,12 +8338,14 @@
"cmpw rscratch1, zr\t# EQ on successful write"
%}
- ins_encode(aarch64_enc_cmpxchg(mem, oldval, newval));
+ ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval));
ins_pipe(pipe_slow);
%}
-// this has to be implemented as a CAS
+// storeIConditional also has acquire semantics, for no better reason
+// than matching storeLConditional. At the time of writing this
+// comment storeIConditional was not used anywhere by AArch64.
instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr)
%{
match(Set cr (StoreIConditional mem (Binary oldval newval)));
@@ -8398,7 +8357,7 @@
"cmpw rscratch1, zr\t# EQ on successful write"
%}
- ins_encode(aarch64_enc_cmpxchgw(mem, oldval, newval));
+ ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval));
ins_pipe(pipe_slow);
%}
--- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -1210,7 +1210,7 @@
INSN(ldrs, 0b00, 1);
INSN(ldrd, 0b01, 1);
- INSN(ldrq, 0x10, 1);
+ INSN(ldrq, 0b10, 1);
#undef INSN
@@ -2285,13 +2285,13 @@
#undef INSN
// Table vector lookup
-#define INSN(NAME, op) \
- void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, unsigned registers, FloatRegister Vm) { \
- starti; \
- assert(T == T8B || T == T16B, "invalid arrangement"); \
- assert(0 < registers && registers <= 4, "invalid number of registers"); \
- f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21), rf(Vm, 16), f(0, 15); \
- f(registers - 1, 14, 13), f(op, 12),f(0b00, 11, 10), rf(Vn, 5), rf(Vd, 0); \
+#define INSN(NAME, op) \
+ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, unsigned registers, FloatRegister Vm) { \
+ starti; \
+ assert(T == T8B || T == T16B, "invalid arrangement"); \
+ assert(0 < registers && registers <= 4, "invalid number of registers"); \
+ f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21), rf(Vm, 16), f(0, 15); \
+ f(registers - 1, 14, 13), f(op, 12),f(0b00, 11, 10), rf(Vn, 5), rf(Vd, 0); \
}
INSN(tbl, 0);
@@ -2299,6 +2299,7 @@
#undef INSN
+ // AdvSIMD two-reg misc
#define INSN(NAME, U, opcode) \
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \
starti; \
@@ -2316,10 +2317,19 @@
#define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H)
INSN(rev32, 1, 0b00000);
+private:
+ INSN(_rbit, 1, 0b00101);
+public:
+
#undef ASSERTION
#define ASSERTION (T == T8B || T == T16B)
INSN(rev16, 0, 0b00001);
+ // RBIT only allows T8B and T16B but encodes them oddly. Argh...
+ void rbit(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {
+ assert((ASSERTION), MSG);
+ _rbit(Vd, SIMD_Arrangement(T & 1 | 0b010), Vn);
+ }
#undef ASSERTION
#undef MSG
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -3043,7 +3043,9 @@
// register obj is destroyed afterwards.
BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
+ assert(bs->kind() == BarrierSet::CardTableForRS ||
+ bs->kind() == BarrierSet::CardTableExtension,
+ "Wrong barrier set kind");
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -917,6 +917,8 @@
void cmpptr(Register src1, Address src2);
+ // Various forms of CAS
+
void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp,
Label &suceed, Label *fail);
@@ -938,6 +940,23 @@
str(rscratch2, adr);
}
+ // A generic CAS; success or failure is in the EQ flag.
+ template <typename T1, typename T2>
+ void cmpxchg(Register addr, Register expected, Register new_val,
+ T1 load_insn,
+ void (MacroAssembler::*cmp_insn)(Register, Register),
+ T2 store_insn,
+ Register tmp = rscratch1) {
+ Label retry_load, done;
+ bind(retry_load);
+ (this->*load_insn)(tmp, addr);
+ (this->*cmp_insn)(tmp, expected);
+ br(Assembler::NE, done);
+ (this->*store_insn)(tmp, new_val, addr);
+ cbnzw(tmp, retry_load);
+ bind(done);
+ }
+
// Calls
address trampoline_call(Address entry, CodeBuffer *cbuf = NULL);
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -691,7 +691,7 @@
__ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2);
__ pop(RegSet::range(r0, r29), sp); // integer registers except lr & sp }
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
case BarrierSet::ModRef:
break;
@@ -731,7 +731,7 @@
__ pop(RegSet::range(r0, r29), sp); // integer registers except lr & sp }
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
@@ -2364,7 +2364,7 @@
* c_rarg3 - int* table
*
* Ouput:
- * rax - int crc result
+ * r0 - int crc result
*/
address generate_updateBytesCRC32C() {
assert(UseCRC32CIntrinsics, "what are we doing here?");
@@ -2435,6 +2435,69 @@
return start;
}
+ void ghash_multiply(FloatRegister result_lo, FloatRegister result_hi,
+ FloatRegister a, FloatRegister b, FloatRegister a1_xor_a0,
+ FloatRegister tmp1, FloatRegister tmp2, FloatRegister tmp3, FloatRegister tmp4) {
+ // Karatsuba multiplication performs a 128*128 -> 256-bit
+ // multiplication in three 128-bit multiplications and a few
+ // additions.
+ //
+ // (C1:C0) = A1*B1, (D1:D0) = A0*B0, (E1:E0) = (A0+A1)(B0+B1)
+ // (A1:A0)(B1:B0) = C1:(C0+C1+D1+E1):(D1+C0+D0+E0):D0
+ //
+ // Inputs:
+ //
+ // A0 in a.d[0] (subkey)
+ // A1 in a.d[1]
+ // (A1+A0) in a1_xor_a0.d[0]
+ //
+ // B0 in b.d[0] (state)
+ // B1 in b.d[1]
+
+ __ ext(tmp1, __ T16B, b, b, 0x08);
+ __ pmull2(result_hi, __ T1Q, b, a, __ T2D); // A1*B1
+ __ eor(tmp1, __ T16B, tmp1, b); // (B1+B0)
+ __ pmull(result_lo, __ T1Q, b, a, __ T1D); // A0*B0
+ __ pmull(tmp2, __ T1Q, tmp1, a1_xor_a0, __ T1D); // (A1+A0)(B1+B0)
+
+ __ ext(tmp4, __ T16B, result_lo, result_hi, 0x08);
+ __ eor(tmp3, __ T16B, result_hi, result_lo); // A1*B1+A0*B0
+ __ eor(tmp2, __ T16B, tmp2, tmp4);
+ __ eor(tmp2, __ T16B, tmp2, tmp3);
+
+ // Register pair <result_hi:result_lo> holds the result of carry-less multiplication
+ __ ins(result_hi, __ D, tmp2, 0, 1);
+ __ ins(result_lo, __ D, tmp2, 1, 0);
+ }
+
+ void ghash_reduce(FloatRegister result, FloatRegister lo, FloatRegister hi,
+ FloatRegister p, FloatRegister z, FloatRegister t1) {
+ const FloatRegister t0 = result;
+
+ // The GCM field polynomial f is z^128 + p(z), where p =
+ // z^7+z^2+z+1.
+ //
+ // z^128 === -p(z) (mod (z^128 + p(z)))
+ //
+ // so, given that the product we're reducing is
+ // a == lo + hi * z^128
+ // substituting,
+ // === lo - hi * p(z) (mod (z^128 + p(z)))
+ //
+ // we reduce by multiplying hi by p(z) and subtracting the result
+ // from (i.e. XORing it with) lo. Because p has no nonzero high
+ // bits we can do this with two 64-bit multiplications, lo*p and
+ // hi*p.
+
+ __ pmull2(t0, __ T1Q, hi, p, __ T2D);
+ __ ext(t1, __ T16B, t0, z, 8);
+ __ eor(hi, __ T16B, hi, t1);
+ __ ext(t1, __ T16B, z, t0, 8);
+ __ eor(lo, __ T16B, lo, t1);
+ __ pmull(t0, __ T1Q, hi, p, __ T1D);
+ __ eor(result, __ T16B, lo, t0);
+ }
+
/**
* Arguments:
*
@@ -2448,10 +2511,27 @@
* Updated state at c_rarg0
*/
address generate_ghash_processBlocks() {
- __ align(CodeEntryAlignment);
- Label L_ghash_loop, L_exit;
+ // Bafflingly, GCM uses little-endian for the byte order, but
+ // big-endian for the bit order. For example, the polynomial 1 is
+ // represented as the 16-byte string 80 00 00 00 | 12 bytes of 00.
+ //
+ // So, we must either reverse the bytes in each word and do
+ // everything big-endian or reverse the bits in each byte and do
+ // it little-endian. On AArch64 it's more idiomatic to reverse
+ // the bits in each byte (we have an instruction, RBIT, to do
+ // that) and keep the data in little-endian bit order throught the
+ // calculation, bit-reversing the inputs and outputs.
StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
+ __ align(wordSize * 2);
+ address p = __ pc();
+ __ emit_int64(0x87); // The low-order bits of the field
+ // polynomial (i.e. p = z^7+z^2+z+1)
+ // repeated in the low and high parts of a
+ // 128-bit vector
+ __ emit_int64(0x87);
+
+ __ align(CodeEntryAlignment);
address start = __ pc();
Register state = c_rarg0;
@@ -2462,104 +2542,43 @@
FloatRegister vzr = v30;
__ eor(vzr, __ T16B, vzr, vzr); // zero register
- __ mov(v26, __ T16B, 1);
- __ mov(v27, __ T16B, 63);
- __ mov(v28, __ T16B, 62);
- __ mov(v29, __ T16B, 57);
-
- __ ldrq(v6, Address(state));
- __ ldrq(v16, Address(subkeyH));
-
- __ ext(v0, __ T16B, v6, v6, 0x08);
- __ ext(v1, __ T16B, v16, v16, 0x08);
- __ eor(v16, __ T16B, v16, v1);
-
- __ bind(L_ghash_loop);
-
- __ ldrq(v2, Address(__ post(data, 0x10)));
- __ rev64(v2, __ T16B, v2); // swap data
-
- __ ext(v6, __ T16B, v0, v0, 0x08);
- __ eor(v6, __ T16B, v6, v2);
- __ ext(v2, __ T16B, v6, v6, 0x08);
-
- __ pmull2(v7, __ T1Q, v2, v1, __ T2D); // A1*B1
- __ eor(v6, __ T16B, v6, v2);
- __ pmull(v5, __ T1Q, v2, v1, __ T1D); // A0*B0
- __ pmull(v20, __ T1Q, v6, v16, __ T1D); // (A1 + A0)(B1 + B0)
-
- __ ext(v21, __ T16B, v5, v7, 0x08);
- __ eor(v18, __ T16B, v7, v5); // A1*B1 xor A0*B0
- __ eor(v20, __ T16B, v20, v21);
- __ eor(v20, __ T16B, v20, v18);
-
- // Registers pair <v7:v5> holds the result of carry-less multiplication
- __ ins(v7, __ D, v20, 0, 1);
- __ ins(v5, __ D, v20, 1, 0);
-
- // Result of the multiplication is shifted by one bit position
- // [X3:X2:X1:X0] = [X3:X2:X1:X0] << 1
- __ ushr(v18, __ T2D, v5, -63 & 63);
- __ ins(v25, __ D, v18, 1, 0);
- __ ins(v25, __ D, vzr, 0, 0);
- __ ushl(v5, __ T2D, v5, v26);
- __ orr(v5, __ T16B, v5, v25);
-
- __ ushr(v19, __ T2D, v7, -63 & 63);
- __ ins(v19, __ D, v19, 1, 0);
- __ ins(v19, __ D, v18, 0, 1);
- __ ushl(v7, __ T2D, v7, v26);
- __ orr(v6, __ T16B, v7, v19);
-
- __ ins(v24, __ D, v5, 0, 1);
-
- // A = X0 << 63
- __ ushl(v21, __ T2D, v5, v27);
-
- // A = X0 << 62
- __ ushl(v22, __ T2D, v5, v28);
-
- // A = X0 << 57
- __ ushl(v23, __ T2D, v5, v29);
-
- // D = X1^A^B^C
- __ eor(v21, __ T16B, v21, v22);
- __ eor(v21, __ T16B, v21, v23);
- __ eor(v21, __ T16B, v21, v24);
- __ ins(v5, __ D, v21, 1, 0);
-
- // [E1:E0] = [D:X0] >> 1
- __ ushr(v20, __ T2D, v5, -1 & 63);
- __ ushl(v18, __ T2D, v5, v27);
- __ ext(v25, __ T16B, v18, vzr, 0x08);
- __ orr(v19, __ T16B, v20, v25);
-
- __ eor(v7, __ T16B, v5, v19);
-
- // [F1:F0] = [D:X0] >> 2
- __ ushr(v20, __ T2D, v5, -2 & 63);
- __ ushl(v18, __ T2D, v5, v28);
- __ ins(v25, __ D, v18, 0, 1);
- __ orr(v19, __ T16B, v20, v25);
-
- __ eor(v7, __ T16B, v7, v19);
-
- // [G1:G0] = [D:X0] >> 7
- __ ushr(v20, __ T2D, v5, -7 & 63);
- __ ushl(v18, __ T2D, v5, v29);
- __ ins(v25, __ D, v18, 0, 1);
- __ orr(v19, __ T16B, v20, v25);
-
- // [H1:H0] = [D^E1^F1^G1:X0^E0^F0^G0]
- __ eor(v7, __ T16B, v7, v19);
-
- // Result = [H1:H0]^[X3:X2]
- __ eor(v0, __ T16B, v7, v6);
-
- __ subs(blocks, blocks, 1);
- __ cbnz(blocks, L_ghash_loop);
-
- __ ext(v1, __ T16B, v0, v0, 0x08);
+ __ ldrq(v0, Address(state));
+ __ ldrq(v1, Address(subkeyH));
+
+ __ rev64(v0, __ T16B, v0); // Bit-reverse words in state and subkeyH
+ __ rbit(v0, __ T16B, v0);
+ __ rev64(v1, __ T16B, v1);
+ __ rbit(v1, __ T16B, v1);
+
+ __ ldrq(v26, p);
+
+ __ ext(v16, __ T16B, v1, v1, 0x08); // long-swap subkeyH into v1
+ __ eor(v16, __ T16B, v16, v1); // xor subkeyH into subkeyL (Karatsuba: (A1+A0))
+
+ {
+ Label L_ghash_loop;
+ __ bind(L_ghash_loop);
+
+ __ ldrq(v2, Address(__ post(data, 0x10))); // Load the data, bit
+ // reversing each byte
+ __ rbit(v2, __ T16B, v2);
+ __ eor(v2, __ T16B, v0, v2); // bit-swapped data ^ bit-swapped state
+
+ // Multiply state in v2 by subkey in v1
+ ghash_multiply(/*result_lo*/v5, /*result_hi*/v7,
+ /*a*/v1, /*b*/v2, /*a1_xor_a0*/v16,
+ /*temps*/v6, v20, v18, v21);
+ // Reduce v7:v5 by the field polynomial
+ ghash_reduce(v0, v5, v7, v26, vzr, v20);
+
+ __ sub(blocks, blocks, 1);
+ __ cbnz(blocks, L_ghash_loop);
+ }
+
+ // The bit-reversed result is at this point in v0
+ __ rev64(v1, __ T16B, v0);
+ __ rbit(v1, __ T16B, v1);
+
__ st1(v1, __ T16B, state);
__ ret(lr);
--- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -186,7 +186,7 @@
}
break;
#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
if (val == noreg) {
--- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -177,6 +177,12 @@
if (UseCRC32 && (auxv & HWCAP_CRC32) == 0) {
warning("UseCRC32 specified, but not supported on this CPU");
}
+
+ if (UseAdler32Intrinsics) {
+ warning("Adler32Intrinsics not available on this CPU.");
+ FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+ }
+
if (auxv & HWCAP_AES) {
UseAES = UseAES || FLAG_IS_DEFAULT(UseAES);
UseAESIntrinsics =
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -2614,7 +2614,7 @@
void MacroAssembler::card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp) {
CardTableModRefBS* bs =
barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
- assert(bs->kind() == BarrierSet::CardTableModRef ||
+ assert(bs->kind() == BarrierSet::CardTableForRS ||
bs->kind() == BarrierSet::CardTableExtension, "wrong barrier");
#ifdef ASSERT
cmpdi(CCR0, Rnew_val, 0);
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -656,7 +656,7 @@
__ bind(filtered);
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
case BarrierSet::ModRef:
break;
@@ -697,7 +697,7 @@
}
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
Label Lskip_loop, Lstore_loop;
--- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -105,7 +105,7 @@
}
break;
#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
Label Lnull, Ldone;
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -200,6 +200,11 @@
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
+ if (UseAdler32Intrinsics) {
+ warning("Adler32Intrinsics not available on this CPU.");
+ FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+ }
+
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
UseMultiplyToLenIntrinsic = true;
}
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -3958,7 +3958,7 @@
if (new_val == G0) return;
CardTableModRefBS* bs =
barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
- assert(bs->kind() == BarrierSet::CardTableModRef ||
+ assert(bs->kind() == BarrierSet::CardTableForRS ||
bs->kind() == BarrierSet::CardTableExtension, "wrong barrier");
card_table_write(bs->byte_map_base, tmp, store_addr);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "gc/shared/memset_with_concurrent_readers.hpp"
+#include "runtime/prefetch.inline.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+#if INCLUDE_ALL_GCS
+
+// An implementation of memset, for use when there may be concurrent
+// readers of the region being stored into.
+//
+// We can't use the standard library memset if it is implemented using
+// block initializing stores. Doing so can result in concurrent readers
+// seeing spurious zeros.
+//
+// We can't use the obvious C/C++ for-loop, because the compiler may
+// recognize the idiomatic loop and optimize it into a call to the
+// standard library memset; we've seen exactly this happen with, for
+// example, Solaris Studio 12.3. Hence the use of inline assembly
+// code, hiding loops from the compiler's optimizer.
+//
+// We don't attempt to use the standard library memset when it is safe
+// to do so. We could conservatively do so by detecting the presence
+// of block initializing stores (VM_Version::has_blk_init()), but the
+// implementation provided here should be sufficient.
+
+inline void fill_subword(void* start, void* end, int value) {
+ STATIC_ASSERT(BytesPerWord == 8);
+ assert(pointer_delta(end, start, 1) < BytesPerWord, "precondition");
+ // Dispatch on (end - start).
+ void* pc;
+ __asm__ volatile(
+ // offset := (7 - (end - start)) + 3
+ // 3 instructions from rdpc to DISPATCH
+ " sub %[offset], %[end], %[offset]\n\t" // offset := start - end
+ " sllx %[offset], 2, %[offset]\n\t" // scale offset for instruction size of 4
+ " add %[offset], 40, %[offset]\n\t" // offset += 10 * instruction size
+ " rd %pc, %[pc]\n\t" // dispatch on scaled offset
+ " jmpl %[pc]+%[offset], %g0\n\t"
+ " nop\n\t"
+ // DISPATCH: no direct reference, but without it the store block may be elided.
+ "1:\n\t"
+ " stb %[value], [%[end]-7]\n\t" // end[-7] = value
+ " stb %[value], [%[end]-6]\n\t"
+ " stb %[value], [%[end]-5]\n\t"
+ " stb %[value], [%[end]-4]\n\t"
+ " stb %[value], [%[end]-3]\n\t"
+ " stb %[value], [%[end]-2]\n\t"
+ " stb %[value], [%[end]-1]\n\t" // end[-1] = value
+ : /* no outputs */
+ [pc] "&=r" (pc) // temp
+ : [offset] "&+r" (start),
+ [end] "r" (end),
+ [value] "r" (value)
+ : "memory");
+}
+
+void memset_with_concurrent_readers(void* to, int value, size_t size) {
+ Prefetch::write(to, 0);
+ void* end = static_cast<char*>(to) + size;
+ if (size >= BytesPerWord) {
+ // Fill any partial word prefix.
+ uintx* aligned_to = static_cast<uintx*>(align_ptr_up(to, BytesPerWord));
+ fill_subword(to, aligned_to, value);
+
+ // Compute fill word.
+ STATIC_ASSERT(BitsPerByte == 8);
+ STATIC_ASSERT(BitsPerWord == 64);
+ uintx xvalue = value & 0xff;
+ xvalue |= (xvalue << 8);
+ xvalue |= (xvalue << 16);
+ xvalue |= (xvalue << 32);
+
+ uintx* aligned_end = static_cast<uintx*>(align_ptr_down(end, BytesPerWord));
+ assert(aligned_to <= aligned_end, "invariant");
+
+ // for ( ; aligned_to < aligned_end; ++aligned_to) {
+ // *aligned_to = xvalue;
+ // }
+ uintptr_t temp;
+ __asm__ volatile(
+ // Unroll loop x8.
+ " sub %[aend], %[ato], %[temp]\n\t"
+ " cmp %[temp], 56\n\t" // cc := (aligned_end - aligned_to) > 7 words
+ " ba %xcc, 2f\n\t" // goto TEST always
+ " sub %[aend], 56, %[temp]\n\t" // limit := aligned_end - 7 words
+ // LOOP:
+ "1:\n\t" // unrolled x8 store loop top
+ " cmp %[temp], %[ato]\n\t" // cc := limit > (next) aligned_to
+ " stx %[xvalue], [%[ato]-64]\n\t" // store 8 words, aligned_to pre-incremented
+ " stx %[xvalue], [%[ato]-56]\n\t"
+ " stx %[xvalue], [%[ato]-48]\n\t"
+ " stx %[xvalue], [%[ato]-40]\n\t"
+ " stx %[xvalue], [%[ato]-32]\n\t"
+ " stx %[xvalue], [%[ato]-24]\n\t"
+ " stx %[xvalue], [%[ato]-16]\n\t"
+ " stx %[xvalue], [%[ato]-8]\n\t"
+ // TEST:
+ "2:\n\t"
+ " bgu,a %xcc, 1b\n\t" // goto LOOP if more than 7 words remaining
+ " add %[ato], 64, %[ato]\n\t" // aligned_to += 8, for next iteration
+ // Fill remaining < 8 full words.
+ // Dispatch on (aligned_end - aligned_to).
+ // offset := (7 - (aligned_end - aligned_to)) + 3
+ // 3 instructions from rdpc to DISPATCH
+ " sub %[ato], %[aend], %[ato]\n\t" // offset := aligned_to - aligned_end
+ " srax %[ato], 1, %[ato]\n\t" // scale offset for instruction size of 4
+ " add %[ato], 40, %[ato]\n\t" // offset += 10 * instruction size
+ " rd %pc, %[temp]\n\t" // dispatch on scaled offset
+ " jmpl %[temp]+%[ato], %g0\n\t"
+ " nop\n\t"
+ // DISPATCH: no direct reference, but without it the store block may be elided.
+ "3:\n\t"
+ " stx %[xvalue], [%[aend]-56]\n\t" // aligned_end[-7] = xvalue
+ " stx %[xvalue], [%[aend]-48]\n\t"
+ " stx %[xvalue], [%[aend]-40]\n\t"
+ " stx %[xvalue], [%[aend]-32]\n\t"
+ " stx %[xvalue], [%[aend]-24]\n\t"
+ " stx %[xvalue], [%[aend]-16]\n\t"
+ " stx %[xvalue], [%[aend]-8]\n\t" // aligned_end[-1] = xvalue
+ : /* no outputs */
+ [temp] "&=r" (temp)
+ : [ato] "&+r" (aligned_to),
+ [aend] "r" (aligned_end),
+ [xvalue] "r" (xvalue)
+ : "cc", "memory");
+ to = aligned_end; // setup for suffix
+ }
+ // Fill any partial word suffix. Also the prefix if size < BytesPerWord.
+ fill_subword(to, end, value);
+}
+
+#endif // INCLUDE_ALL_GCS
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -981,7 +981,7 @@
__ restore();
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
case BarrierSet::ModRef:
break;
@@ -1014,7 +1014,7 @@
__ restore();
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
@@ -5110,6 +5110,188 @@
return start;
}
+#define ADLER32_NUM_TEMPS 16
+
+ /**
+ * Arguments:
+ *
+ * Inputs:
+ * O0 - int adler
+ * O1 - byte* buff
+ * O2 - int len
+ *
+ * Output:
+ * O0 - int adler result
+ */
+ address generate_updateBytesAdler32() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "updateBytesAdler32");
+ address start = __ pc();
+
+ Label L_cleanup_loop, L_cleanup_loop_check;
+ Label L_main_loop_check, L_main_loop, L_inner_loop, L_inner_loop_check;
+ Label L_nmax_check_done;
+
+ // Aliases
+ Register s1 = O0;
+ Register s2 = O3;
+ Register buff = O1;
+ Register len = O2;
+ Register temp[ADLER32_NUM_TEMPS] = {L0, L1, L2, L3, L4, L5, L6, L7, I0, I1, I2, I3, I4, I5, G3, I7};
+
+ // Max number of bytes we can process before having to take the mod
+ // 0x15B0 is 5552 in decimal, the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ unsigned long NMAX = 0x15B0;
+
+ // Zero-out the upper bits of len
+ __ clruwu(len);
+
+ // Create the mask 0xFFFF
+ __ set64(0x00FFFF, O4, O5); // O5 is the temp register
+
+ // s1 is initialized to the lower 16 bits of adler
+ // s2 is initialized to the upper 16 bits of adler
+ __ srlx(O0, 16, O5); // adler >> 16
+ __ and3(O0, O4, s1); // s1 = (adler & 0xFFFF)
+ __ and3(O5, O4, s2); // s2 = ((adler >> 16) & 0xFFFF)
+
+ // The pipelined loop needs at least 16 elements for 1 iteration
+ // It does check this, but it is more effective to skip to the cleanup loop
+ // Setup the constant for cutoff checking
+ __ mov(15, O4);
+
+ // Check if we are above the cutoff, if not go to the cleanup loop immediately
+ __ cmp_and_br_short(len, O4, Assembler::lessEqualUnsigned, Assembler::pt, L_cleanup_loop_check);
+
+ // Free up some registers for our use
+ for (int i = 0; i < ADLER32_NUM_TEMPS; i++) {
+ __ movxtod(temp[i], as_FloatRegister(2*i));
+ }
+
+ // Loop maintenance stuff is done at the end of the loop, so skip to there
+ __ ba_short(L_main_loop_check);
+
+ __ BIND(L_main_loop);
+
+ // Prologue for inner loop
+ __ ldub(buff, 0, L0);
+ __ dec(O5);
+
+ for (int i = 1; i < 8; i++) {
+ __ ldub(buff, i, temp[i]);
+ }
+
+ __ inc(buff, 8);
+
+ // Inner loop processes 16 elements at a time, might never execute if only 16 elements
+ // to be processed by the outter loop
+ __ ba_short(L_inner_loop_check);
+
+ __ BIND(L_inner_loop);
+
+ for (int i = 0; i < 8; i++) {
+ __ ldub(buff, (2*i), temp[(8+(2*i)) % ADLER32_NUM_TEMPS]);
+ __ add(s1, temp[i], s1);
+ __ ldub(buff, (2*i)+1, temp[(8+(2*i)+1) % ADLER32_NUM_TEMPS]);
+ __ add(s2, s1, s2);
+ }
+
+ // Original temp 0-7 used and new loads to temp 0-7 issued
+ // temp 8-15 ready to be consumed
+ __ add(s1, I0, s1);
+ __ dec(O5);
+ __ add(s2, s1, s2);
+ __ add(s1, I1, s1);
+ __ inc(buff, 16);
+ __ add(s2, s1, s2);
+
+ for (int i = 0; i < 6; i++) {
+ __ add(s1, temp[10+i], s1);
+ __ add(s2, s1, s2);
+ }
+
+ __ BIND(L_inner_loop_check);
+ __ nop();
+ __ cmp_and_br_short(O5, 0, Assembler::notEqual, Assembler::pt, L_inner_loop);
+
+ // Epilogue
+ for (int i = 0; i < 4; i++) {
+ __ ldub(buff, (2*i), temp[8+(2*i)]);
+ __ add(s1, temp[i], s1);
+ __ ldub(buff, (2*i)+1, temp[8+(2*i)+1]);
+ __ add(s2, s1, s2);
+ }
+
+ __ add(s1, temp[4], s1);
+ __ inc(buff, 8);
+
+ for (int i = 0; i < 11; i++) {
+ __ add(s2, s1, s2);
+ __ add(s1, temp[5+i], s1);
+ }
+
+ __ add(s2, s1, s2);
+
+ // Take the mod for s1 and s2
+ __ set64(0xFFF1, L0, L1);
+ __ udivx(s1, L0, L1);
+ __ udivx(s2, L0, L2);
+ __ mulx(L0, L1, L1);
+ __ mulx(L0, L2, L2);
+ __ sub(s1, L1, s1);
+ __ sub(s2, L2, s2);
+
+ // Make sure there is something left to process
+ __ BIND(L_main_loop_check);
+ __ set64(NMAX, L0, L1);
+ // k = len < NMAX ? len : NMAX
+ __ cmp_and_br_short(len, L0, Assembler::greaterEqualUnsigned, Assembler::pt, L_nmax_check_done);
+ __ andn(len, 0x0F, L0); // only loop a multiple of 16 times
+ __ BIND(L_nmax_check_done);
+ __ mov(L0, O5);
+ __ sub(len, L0, len); // len -= k
+
+ __ srlx(O5, 4, O5); // multiplies of 16
+ __ cmp_and_br_short(O5, 0, Assembler::notEqual, Assembler::pt, L_main_loop);
+
+ // Restore anything we used, take the mod one last time, combine and return
+ // Restore any registers we saved
+ for (int i = 0; i < ADLER32_NUM_TEMPS; i++) {
+ __ movdtox(as_FloatRegister(2*i), temp[i]);
+ }
+
+ // There might be nothing left to process
+ __ ba_short(L_cleanup_loop_check);
+
+ __ BIND(L_cleanup_loop);
+ __ ldub(buff, 0, O4); // load single byte form buffer
+ __ inc(buff); // buff++
+ __ add(s1, O4, s1); // s1 += *buff++;
+ __ dec(len); // len--
+ __ add(s1, s2, s2); // s2 += s1;
+ __ BIND(L_cleanup_loop_check);
+ __ nop();
+ __ cmp_and_br_short(len, 0, Assembler::notEqual, Assembler::pt, L_cleanup_loop);
+
+ // Take the mod one last time
+ __ set64(0xFFF1, O1, O2);
+ __ udivx(s1, O1, O2);
+ __ udivx(s2, O1, O5);
+ __ mulx(O1, O2, O2);
+ __ mulx(O1, O5, O5);
+ __ sub(s1, O2, s1);
+ __ sub(s2, O5, s2);
+
+ // Combine lower bits and higher bits
+ __ sllx(s2, 16, s2); // s2 = s2 << 16
+ __ or3(s1, s2, s1); // adler = s2 | s1
+ // Final return value is in O0
+ __ retl();
+ __ delayed()->nop();
+
+ return start;
+ }
+
void generate_initial() {
// Generates all stubs and initializes the entry points
@@ -5206,6 +5388,11 @@
if (UseCRC32CIntrinsics) {
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
}
+
+ // generate Adler32 intrinsics code
+ if (UseAdler32Intrinsics) {
+ StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
+ }
}
--- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -41,7 +41,7 @@
enum /* platform_dependent_constants */ {
// %%%%%%%% May be able to shrink this a lot
code_size1 = 20000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 24000 // simply increase if too small (assembler will crash if too small)
+ code_size2 = 27000 // simply increase if too small (assembler will crash if too small)
};
class Sparc {
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -91,7 +91,7 @@
}
break;
#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
if (index == noreg ) {
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -85,27 +85,6 @@
_supports_cx8 = has_v9();
_supports_atomic_getset4 = true; // swap instruction
- // There are Fujitsu Sparc64 CPUs which support blk_init as well so
- // we have to take this check out of the 'is_niagara()' block below.
- if (has_blk_init()) {
- // When using CMS or G1, we cannot use memset() in BOT updates
- // because the sun4v/CMT version in libc_psr uses BIS which
- // exposes "phantom zeros" to concurrent readers. See 6948537.
- if (FLAG_IS_DEFAULT(UseMemSetInBOT) && (UseConcMarkSweepGC || UseG1GC)) {
- FLAG_SET_DEFAULT(UseMemSetInBOT, false);
- }
- // Issue a stern warning if the user has explicitly set
- // UseMemSetInBOT (it is known to cause issues), but allow
- // use for experimentation and debugging.
- if (UseConcMarkSweepGC || UseG1GC) {
- if (UseMemSetInBOT) {
- assert(!FLAG_IS_DEFAULT(UseMemSetInBOT), "Error");
- warning("Experimental flag -XX:+UseMemSetInBOT is known to cause instability"
- " on sun4v; please understand that you are using at your own risk!");
- }
- }
- }
-
if (is_niagara()) {
// Indirect branch is the same cost as direct
if (FLAG_IS_DEFAULT(UseInlineCaches)) {
@@ -377,6 +356,15 @@
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
}
+ if (UseVIS > 2) {
+ if (FLAG_IS_DEFAULT(UseAdler32Intrinsics)) {
+ FLAG_SET_DEFAULT(UseAdler32Intrinsics, true);
+ }
+ } else if (UseAdler32Intrinsics) {
+ warning("SPARC Adler32 intrinsics require VIS3 instruction support. Intrinsics will be disabled.");
+ FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+ }
+
if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
(cache_line_size > ContendedPaddingWidth))
ContendedPaddingWidth = cache_line_size;
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -394,25 +394,25 @@
int mod_idx = 0;
// We will test if the displacement fits the compressed format and if so
// apply the compression to the displacment iff the result is8bit.
- if (VM_Version::supports_evex() && is_evex_instruction) {
- switch (tuple_type) {
+ if (VM_Version::supports_evex() && _is_evex_instruction) {
+ switch (_tuple_type) {
case EVEX_FV:
- if ((evex_encoding & VEX_W) == VEX_W) {
- mod_idx += 2 + ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
+ if ((_evex_encoding & VEX_W) == VEX_W) {
+ mod_idx += 2 + ((_evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
} else {
- mod_idx = ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
+ mod_idx = ((_evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
}
break;
case EVEX_HV:
- mod_idx = ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
+ mod_idx = ((_evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
break;
case EVEX_FVM:
break;
case EVEX_T1S:
- switch (input_size_in_bits) {
+ switch (_input_size_in_bits) {
case EVEX_8bit:
break;
@@ -433,7 +433,7 @@
case EVEX_T1F:
case EVEX_T2:
case EVEX_T4:
- mod_idx = (input_size_in_bits == EVEX_64bit) ? 1 : 0;
+ mod_idx = (_input_size_in_bits == EVEX_64bit) ? 1 : 0;
break;
case EVEX_T8:
@@ -459,8 +459,8 @@
break;
}
- if (avx_vector_len >= AVX_128bit && avx_vector_len <= AVX_512bit) {
- int disp_factor = tuple_table[tuple_type + mod_idx][avx_vector_len];
+ if (_avx_vector_len >= AVX_128bit && _avx_vector_len <= AVX_512bit) {
+ int disp_factor = tuple_table[_tuple_type + mod_idx][_avx_vector_len];
if ((disp % disp_factor) == 0) {
int new_disp = disp / disp_factor;
if (is8bit(new_disp)) {
@@ -591,7 +591,7 @@
emit_data(disp, rspec, disp32_operand);
}
}
- is_evex_instruction = false;
+ _is_evex_instruction = false;
}
void Assembler::emit_operand(XMMRegister reg, Register base, Register index,
@@ -1229,8 +1229,8 @@
void Assembler::addsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x58, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x58, dst, src, VEX_SIMD_F2);
@@ -1245,8 +1245,8 @@
void Assembler::addss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x58, dst, src, VEX_SIMD_F3);
}
@@ -1254,16 +1254,16 @@
void Assembler::aesdec(XMMRegister dst, Address src) {
assert(VM_Version::supports_aes(), "");
InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDE);
emit_operand(dst, src);
}
void Assembler::aesdec(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_aes(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDE);
emit_int8(0xC0 | encode);
}
@@ -1271,16 +1271,16 @@
void Assembler::aesdeclast(XMMRegister dst, Address src) {
assert(VM_Version::supports_aes(), "");
InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDF);
emit_operand(dst, src);
}
void Assembler::aesdeclast(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_aes(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDF);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1288,16 +1288,16 @@
void Assembler::aesenc(XMMRegister dst, Address src) {
assert(VM_Version::supports_aes(), "");
InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDC);
emit_operand(dst, src);
}
void Assembler::aesenc(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_aes(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDC);
emit_int8(0xC0 | encode);
}
@@ -1305,21 +1305,20 @@
void Assembler::aesenclast(XMMRegister dst, Address src) {
assert(VM_Version::supports_aes(), "");
InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDD);
emit_operand(dst, src);
}
void Assembler::aesenclast(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_aes(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDD);
emit_int8((unsigned char)(0xC0 | encode));
}
-
void Assembler::andl(Address dst, int32_t imm32) {
InstructionMark im(this);
prefix(dst);
@@ -1347,7 +1346,7 @@
void Assembler::andnl(Register dst, Register src1, Register src2) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- int encode = vex_prefix_0F38_and_encode_legacy(dst, src1, src2, false);
+ int encode = vex_prefix_0F38_and_encode_legacy(dst, src1, src2);
emit_int8((unsigned char)0xF2);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1355,7 +1354,7 @@
void Assembler::andnl(Register dst, Register src1, Address src2) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- vex_prefix_0F38_legacy(dst, src1, src2, false);
+ vex_prefix_0F38_legacy(dst, src1, src2);
emit_int8((unsigned char)0xF2);
emit_operand(dst, src2);
}
@@ -1382,7 +1381,7 @@
void Assembler::blsil(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- int encode = vex_prefix_0F38_and_encode_legacy(rbx, dst, src, false);
+ int encode = vex_prefix_0F38_and_encode_legacy(rbx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1390,14 +1389,14 @@
void Assembler::blsil(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- vex_prefix_0F38_legacy(rbx, dst, src, false);
+ vex_prefix_0F38_legacy(rbx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rbx, src);
}
void Assembler::blsmskl(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- int encode = vex_prefix_0F38_and_encode_legacy(rdx, dst, src, false);
+ int encode = vex_prefix_0F38_and_encode_legacy(rdx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1405,14 +1404,14 @@
void Assembler::blsmskl(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- vex_prefix_0F38(rdx, dst, src, false);
+ vex_prefix_0F38_legacy(rdx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rdx, src);
}
void Assembler::blsrl(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- int encode = vex_prefix_0F38_and_encode_legacy(rcx, dst, src, false);
+ int encode = vex_prefix_0F38_and_encode_legacy(rcx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1420,7 +1419,7 @@
void Assembler::blsrl(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- vex_prefix_0F38_legacy(rcx, dst, src, false);
+ vex_prefix_0F38_legacy(rcx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rcx, src);
}
@@ -1569,9 +1568,9 @@
// 0x66 is there. Strangly ucomisd comes out correct
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66);
}
@@ -1580,7 +1579,7 @@
void Assembler::comisd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, true);
+ emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66);
}
@@ -1588,16 +1587,16 @@
void Assembler::comiss(XMMRegister dst, Address src) {
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, true);
+ emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
}
void Assembler::comiss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, true);
+ emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
}
void Assembler::cpuid() {
@@ -1607,12 +1606,12 @@
void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith_nonds(0xE6, dst, src, VEX_SIMD_F3);
+ emit_simd_arith_nonds(0xE6, dst, src, VEX_SIMD_F3, /* no_mask_reg */ false, /* legacy_mode */ true);
}
void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith_nonds(0x5B, dst, src, VEX_SIMD_NONE);
+ emit_simd_arith_nonds(0x5B, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ true);
}
void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
@@ -1627,8 +1626,8 @@
void Assembler::cvtsd2ss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1F;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1F;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x5A, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x5A, dst, src, VEX_SIMD_F2);
@@ -1637,12 +1636,7 @@
void Assembler::cvtsi2sdl(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = 0;
- if (VM_Version::supports_evex()) {
- encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F2, true);
- } else {
- encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, false);
- }
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VM_Version::supports_evex());
emit_int8(0x2A);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1650,9 +1644,9 @@
void Assembler::cvtsi2sdl(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- emit_simd_arith_q(0x2A, dst, src, VEX_SIMD_F2, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ emit_simd_arith(0x2A, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
} else {
emit_simd_arith(0x2A, dst, src, VEX_SIMD_F2);
}
@@ -1660,23 +1654,23 @@
void Assembler::cvtsi2ssl(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::cvtsi2ssl(XMMRegister dst, Address src) {
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith(0x2A, dst, src, VEX_SIMD_F3, true);
+ emit_simd_arith(0x2A, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
}
void Assembler::cvtsi2ssq(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F3, true);
+ int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1688,8 +1682,8 @@
void Assembler::cvtss2sd(XMMRegister dst, Address src) {
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x5A, dst, src, VEX_SIMD_F3);
@@ -1698,14 +1692,14 @@
void Assembler::cvttsd2sil(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, /* no_mask_reg */ true);
emit_int8(0x2C);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::cvttss2sil(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, /* no_mask_reg */ true);
emit_int8(0x2C);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1721,8 +1715,8 @@
void Assembler::divsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x5E, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x5E, dst, src, VEX_SIMD_F2);
@@ -1740,8 +1734,8 @@
void Assembler::divss(XMMRegister dst, Address src) {
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
NOT_LP64(assert(VM_Version::supports_sse(), ""));
emit_simd_arith(0x5E, dst, src, VEX_SIMD_F3);
@@ -1995,8 +1989,16 @@
void Assembler::movapd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex()) {
- emit_simd_arith_nonds_q(0x28, dst, src, VEX_SIMD_66, true);
+ if (VM_Version::supports_avx512novl()) {
+ int vector_len = AVX_512bit;
+ int dst_enc = dst->encoding();
+ int src_enc = src->encoding();
+ int encode = vex_prefix_and_encode(dst_enc, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
+ emit_int8(0x28);
+ emit_int8((unsigned char)(0xC0 | encode));
+ } else if (VM_Version::supports_evex()) {
+ emit_simd_arith_nonds_q(0x28, dst, src, VEX_SIMD_66);
} else {
emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_66);
}
@@ -2004,13 +2006,19 @@
void Assembler::movaps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_NONE);
+ if (VM_Version::supports_avx512novl()) {
+ int vector_len = AVX_512bit;
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, vector_len);
+ emit_int8(0x28);
+ emit_int8((unsigned char)(0xC0 | encode));
+ } else {
+ emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_NONE);
+ }
}
void Assembler::movlhps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode(dst, src, src, VEX_SIMD_NONE, true, VEX_OPCODE_0F,
- false, AVX_128bit);
+ int encode = simd_prefix_and_encode(dst, src, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
emit_int8(0x16);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -2023,48 +2031,54 @@
emit_operand(dst, src);
}
-void Assembler::kmovq(KRegister dst, KRegister src) {
+void Assembler::kmovql(KRegister dst, KRegister src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE,
- true, VEX_OPCODE_0F, true);
+ /* no_mask_reg */ true, VEX_OPCODE_0F, /* rex_w */ true);
emit_int8((unsigned char)0x90);
emit_int8((unsigned char)(0xC0 | encode));
}
-void Assembler::kmovq(KRegister dst, Address src) {
+void Assembler::kmovql(KRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
int dst_enc = dst->encoding();
int nds_enc = 0;
vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_NONE,
- VEX_OPCODE_0F, true, AVX_128bit, true, true);
+ VEX_OPCODE_0F, /* vex_w */ true, AVX_128bit, /* legacy_mode */ true, /* no_reg_mask */ true);
emit_int8((unsigned char)0x90);
emit_operand((Register)dst, src);
}
-void Assembler::kmovq(Address dst, KRegister src) {
+void Assembler::kmovql(Address dst, KRegister src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
int src_enc = src->encoding();
int nds_enc = 0;
vex_prefix(dst, nds_enc, src_enc, VEX_SIMD_NONE,
- VEX_OPCODE_0F, true, AVX_128bit, true, true);
+ VEX_OPCODE_0F, /* vex_w */ true, AVX_128bit, /* legacy_mode */ true, /* no_reg_mask */ true);
emit_int8((unsigned char)0x90);
emit_operand((Register)src, dst);
}
void Assembler::kmovql(KRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
- bool supports_bw = VM_Version::supports_avx512bw();
- VexSimdPrefix pre = supports_bw ? VEX_SIMD_F2 : VEX_SIMD_NONE;
- int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, true,
- VEX_OPCODE_0F, supports_bw);
+ VexSimdPrefix pre = !_legacy_mode_bw ? VEX_SIMD_F2 : VEX_SIMD_NONE;
+ int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* legacy_mode */ !_legacy_mode_bw);
emit_int8((unsigned char)0x92);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::kmovdl(KRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
- VexSimdPrefix pre = VM_Version::supports_avx512bw() ? VEX_SIMD_F2 : VEX_SIMD_NONE;
- int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, true, VEX_OPCODE_0F, false);
+ VexSimdPrefix pre = !_legacy_mode_bw ? VEX_SIMD_F2 : VEX_SIMD_NONE;
+ int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, /* no_mask_reg */ true);
+ emit_int8((unsigned char)0x92);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::kmovwl(KRegister dst, Register src) {
+ NOT_LP64(assert(VM_Version::supports_evex(), ""));
+ int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
emit_int8((unsigned char)0x92);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -2088,7 +2102,7 @@
void Assembler::movdl(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, true);
+ int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
emit_int8(0x6E);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -2096,7 +2110,7 @@
void Assembler::movdl(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// swap src/dst to get correct prefix
- int encode = simd_prefix_and_encode(src, dst, VEX_SIMD_66, true);
+ int encode = simd_prefix_and_encode(src, dst, VEX_SIMD_66, /* no_mask_reg */ true);
emit_int8(0x7E);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -2104,11 +2118,11 @@
void Assembler::movdl(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_66, true, VEX_OPCODE_0F);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_reg_mask */ true);
emit_int8(0x6E);
emit_operand(dst, src);
}
@@ -2116,58 +2130,61 @@
void Assembler::movdl(Address dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_66, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_reg_mask */ true);
emit_int8(0x7E);
emit_operand(src, dst);
}
void Assembler::movdqa(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_66);
}
void Assembler::movdqa(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
+ _tuple_type = EVEX_FVM;
}
emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_66);
}
void Assembler::movdqu(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
+ _tuple_type = EVEX_FVM;
}
emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_F3);
}
void Assembler::movdqu(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_F3);
}
void Assembler::movdqu(Address dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_F3, false);
+ _tuple_type = EVEX_FVM;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_F3, /* no_mask_reg */ false);
emit_int8(0x7F);
emit_operand(src, dst);
}
// Move Unaligned 256bit Vector
void Assembler::vmovdqu(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
- if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
int vector_len = AVX_256bit;
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_F3, vector_len);
emit_int8(0x6F);
@@ -2175,67 +2192,100 @@
}
void Assembler::vmovdqu(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
+ _tuple_type = EVEX_FVM;
}
InstructionMark im(this);
int vector_len = AVX_256bit;
- vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false);
+ vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len);
emit_int8(0x6F);
emit_operand(dst, src);
}
void Assembler::vmovdqu(Address dst, XMMRegister src) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
+ _tuple_type = EVEX_FVM;
}
InstructionMark im(this);
int vector_len = AVX_256bit;
// swap src<->dst for encoding
assert(src != xnoreg, "sanity");
- vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false);
+ vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len);
emit_int8(0x7F);
emit_operand(src, dst);
}
// Move Unaligned EVEX enabled Vector (programmable : 8,16,32,64)
-void Assembler::evmovdqu(XMMRegister dst, XMMRegister src, int vector_len) {
+void Assembler::evmovdqul(XMMRegister dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int encode = vex_prefix_and_encode(dst_enc, 0, src_enc, VEX_SIMD_F3, VEX_OPCODE_0F,
- true, vector_len, false, false);
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x6F);
emit_int8((unsigned char)(0xC0 | encode));
}
-void Assembler::evmovdqu(XMMRegister dst, Address src, int vector_len) {
+void Assembler::evmovdqul(XMMRegister dst, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
InstructionMark im(this);
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- vex_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false);
- } else {
- vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false);
- }
+ _tuple_type = EVEX_FVM;
+ }
+ vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len);
emit_int8(0x6F);
emit_operand(dst, src);
}
-void Assembler::evmovdqu(Address dst, XMMRegister src, int vector_len) {
+void Assembler::evmovdqul(Address dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
InstructionMark im(this);
assert(src != xnoreg, "sanity");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- // swap src<->dst for encoding
- vex_prefix_q(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false);
- } else {
- // swap src<->dst for encoding
- vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false);
- }
+ _tuple_type = EVEX_FVM;
+ }
+ // swap src<->dst for encoding
+ vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len);
+ emit_int8(0x7F);
+ emit_operand(src, dst);
+}
+
+void Assembler::evmovdquq(XMMRegister dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(UseAVX > 0, "");
+ int src_enc = src->encoding();
+ int dst_enc = dst->encoding();
+ int encode = vex_prefix_and_encode(dst_enc, 0, src_enc, VEX_SIMD_F3, VEX_OPCODE_0F,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
+ emit_int8(0x6F);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::evmovdquq(XMMRegister dst, Address src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(UseAVX > 2, "");
+ InstructionMark im(this);
+ _tuple_type = EVEX_FVM;
+ vex_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, vector_len);
+ emit_int8(0x6F);
+ emit_operand(dst, src);
+}
+
+void Assembler::evmovdquq(Address dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(UseAVX > 2, "");
+ InstructionMark im(this);
+ assert(src != xnoreg, "sanity");
+ _tuple_type = EVEX_FVM;
+ // swap src<->dst for encoding
+ vex_prefix_q(src, xnoreg, dst, VEX_SIMD_F3, vector_len);
emit_int8(0x7F);
emit_operand(src, dst);
}
@@ -2282,10 +2332,12 @@
void Assembler::movlpd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith(0x12, dst, src, VEX_SIMD_66, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ emit_simd_arith_q(0x12, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
+ } else {
+ emit_simd_arith(0x12, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
+ }
}
void Assembler::movq( MMXRegister dst, Address src ) {
@@ -2312,11 +2364,11 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- simd_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ simd_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, /* no_mask_reg */ true);
} else {
- simd_prefix(dst, src, VEX_SIMD_F3, true, VEX_OPCODE_0F);
+ simd_prefix(dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
}
emit_int8(0x7E);
emit_operand(dst, src);
@@ -2326,12 +2378,12 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- simd_prefix(src, xnoreg, dst, VEX_SIMD_66, true,
- VEX_OPCODE_0F, true, AVX_128bit);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ simd_prefix(src, xnoreg, dst, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* rex_w */ true);
} else {
- simd_prefix(dst, src, VEX_SIMD_66, true);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
}
emit_int8((unsigned char)0xD6);
emit_operand(src, dst);
@@ -2356,7 +2408,7 @@
void Assembler::movsd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- emit_simd_arith_q(0x10, dst, src, VEX_SIMD_F2, true);
+ emit_simd_arith_q(0x10, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
} else {
emit_simd_arith(0x10, dst, src, VEX_SIMD_F2);
}
@@ -2365,9 +2417,9 @@
void Assembler::movsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- emit_simd_arith_nonds_q(0x10, dst, src, VEX_SIMD_F2, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ emit_simd_arith_nonds_q(0x10, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F2);
}
@@ -2377,11 +2429,11 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
simd_prefix_q(src, xnoreg, dst, VEX_SIMD_F2);
} else {
- simd_prefix(src, xnoreg, dst, VEX_SIMD_F2, false);
+ simd_prefix(src, xnoreg, dst, VEX_SIMD_F2, /* no_mask_reg */ false);
}
emit_int8(0x11);
emit_operand(src, dst);
@@ -2389,26 +2441,26 @@
void Assembler::movss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith(0x10, dst, src, VEX_SIMD_F3, true);
+ emit_simd_arith(0x10, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
}
void Assembler::movss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F3, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
}
void Assembler::movss(Address dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_F3, false);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_F3, /* no_mask_reg */ false);
emit_int8(0x11);
emit_operand(src, dst);
}
@@ -2501,8 +2553,8 @@
void Assembler::mulsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x59, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x59, dst, src, VEX_SIMD_F2);
@@ -2521,8 +2573,8 @@
void Assembler::mulss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x59, dst, src, VEX_SIMD_F3);
}
@@ -2831,29 +2883,27 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith(0x67, dst, src, VEX_SIMD_66,
- false, (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith(0x67, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::packuswb(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0x67, dst, src, VEX_SIMD_66,
- false, (VM_Version::supports_avx512dq() == false));
+ emit_simd_arith(0x67, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "some form of AVX must be enabled");
- emit_vex_arith(0x67, dst, nds, src, VEX_SIMD_66, vector_len,
- false, (VM_Version::supports_avx512dq() == false));
+ emit_vex_arith(0x67, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx2(), "");
- int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_3A, true, vector_len);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_3A, /* rex_w */ true, vector_len);
emit_int8(0x00);
emit_int8(0xC0 | encode);
emit_int8(imm8);
@@ -2867,8 +2917,8 @@
void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
assert(VM_Version::supports_sse4_2(), "");
InstructionMark im(this);
- simd_prefix(dst, xnoreg, src, VEX_SIMD_66, false, VEX_OPCODE_0F_3A,
- false, AVX_128bit, true);
+ simd_prefix(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F_3A,
+ /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x61);
emit_operand(dst, src);
emit_int8(imm8);
@@ -2876,8 +2926,8 @@
void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) {
assert(VM_Version::supports_sse4_2(), "");
- int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_3A, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_3A, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x61);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2885,8 +2935,8 @@
void Assembler::pextrd(Register dst, XMMRegister src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F_3A,
- false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+ int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F_3A, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x16);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2894,8 +2944,8 @@
void Assembler::pextrq(Register dst, XMMRegister src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F_3A,
- false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+ int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F_3A, /* rex_w */ true, AVX_128bit, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x16);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2903,8 +2953,8 @@
void Assembler::pinsrd(XMMRegister dst, Register src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, true, VEX_OPCODE_0F_3A,
- false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+ int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F_3A, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x22);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2912,8 +2962,8 @@
void Assembler::pinsrq(XMMRegister dst, Register src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, true, VEX_OPCODE_0F_3A,
- false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+ int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F_3A, /* rex_w */ true, AVX_128bit, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x22);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2922,17 +2972,17 @@
void Assembler::pmovzxbw(XMMRegister dst, Address src) {
assert(VM_Version::supports_sse4_1(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_HVM;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38);
+ _tuple_type = EVEX_HVM;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F_38);
emit_int8(0x30);
emit_operand(dst, src);
}
void Assembler::pmovzxbw(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F_38);
emit_int8(0x30);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -3035,8 +3085,8 @@
void Assembler::pshufb(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_ssse3(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38,
- false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x00);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -3044,33 +3094,34 @@
void Assembler::pshufb(XMMRegister dst, Address src) {
assert(VM_Version::supports_ssse3(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38,
- false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x00);
emit_operand(dst, src);
}
void Assembler::pshufd(XMMRegister dst, XMMRegister src, int mode) {
+ _instruction_uses_vl = true;
assert(isByte(mode), "invalid value");
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_66);
emit_int8(mode & 0xFF);
-
}
void Assembler::pshufd(XMMRegister dst, Address src, int mode) {
+ _instruction_uses_vl = true;
assert(isByte(mode), "invalid value");
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_66, false);
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_mask_reg */ false);
emit_int8(0x70);
emit_operand(dst, src);
emit_int8(mode & 0xFF);
@@ -3079,8 +3130,7 @@
void Assembler::pshuflw(XMMRegister dst, XMMRegister src, int mode) {
assert(isByte(mode), "invalid value");
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_F2, false,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_F2, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
emit_int8(mode & 0xFF);
}
@@ -3089,29 +3139,33 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- InstructionMark im(this);
- simd_prefix(dst, xnoreg, src, VEX_SIMD_F2, false, VEX_OPCODE_0F,
- false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, xnoreg, src, VEX_SIMD_F2, /* no_mask_reg */ false,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x70);
emit_operand(dst, src);
emit_int8(mode & 0xFF);
}
void Assembler::psrldq(XMMRegister dst, int shift) {
- // Shift 128 bit value in xmm register by number of bytes.
+ // Shift left 128 bit value in dst XMMRegister by shift number of bytes.
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ // XMM3 is for /3 encoding: 66 0F 73 /3 ib
+ int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift);
}
void Assembler::pslldq(XMMRegister dst, int shift) {
- // Shift left 128 bit value in xmm register by number of bytes.
+ // Shift left 128 bit value in dst XMMRegister by shift number of bytes.
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode(xmm7, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ // XMM7 is for /7 encoding: 66 0F 73 /7 ib
+ int encode = simd_prefix_and_encode(xmm7, dst, dst, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift);
@@ -3121,16 +3175,16 @@
assert(VM_Version::supports_sse4_1(), "");
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
InstructionMark im(this);
- simd_prefix(dst, xnoreg, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x17);
emit_operand(dst, src);
}
void Assembler::ptest(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x17);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -3142,7 +3196,8 @@
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len, true, false);
+ vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* rex_w */ false,
+ vector_len, /* legacy_mode */ true, /* no_mask_reg */ false);
emit_int8(0x17);
emit_operand(dst, src);
}
@@ -3150,8 +3205,7 @@
void Assembler::vptest(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
int vector_len = AVX_256bit;
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, true, false);
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38, /* legacy_mode */ true);
emit_int8(0x17);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -3160,34 +3214,41 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_simd_arith(0x60, dst, src, VEX_SIMD_66, false, (VM_Version::supports_avx512vlbw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ emit_simd_arith(0x60, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_vlbw);
}
void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0x60, dst, src, VEX_SIMD_66, false, (VM_Version::supports_avx512vlbw() == false));
+ emit_simd_arith(0x60, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_vlbw);
}
void Assembler::punpckldq(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x62, dst, src, VEX_SIMD_66);
}
void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x62, dst, src, VEX_SIMD_66);
}
void Assembler::punpcklqdq(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0x6C, dst, src, VEX_SIMD_66);
+ if (VM_Version::supports_evex()) {
+ emit_simd_arith_q(0x6C, dst, src, VEX_SIMD_66);
+ } else {
+ emit_simd_arith(0x6C, dst, src, VEX_SIMD_66);
+ }
}
void Assembler::push(int32_t imm32) {
@@ -3396,8 +3457,8 @@
void Assembler::sqrtsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x51, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x51, dst, src, VEX_SIMD_F2);
@@ -3416,8 +3477,8 @@
void Assembler::sqrtss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x51, dst, src, VEX_SIMD_F3);
}
@@ -3479,10 +3540,14 @@
void Assembler::subsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- }
- emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_F2);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ }
+ if (VM_Version::supports_evex()) {
+ emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_F2);
+ } else {
+ emit_simd_arith(0x5C, dst, src, VEX_SIMD_F2);
+ }
}
void Assembler::subss(XMMRegister dst, XMMRegister src) {
@@ -3493,8 +3558,8 @@
void Assembler::subss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x5C, dst, src, VEX_SIMD_F3);
}
@@ -3553,9 +3618,9 @@
void Assembler::ucomisd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66);
}
@@ -3564,7 +3629,7 @@
void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, true);
+ emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66);
}
@@ -3573,15 +3638,15 @@
void Assembler::ucomiss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
}
void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, true);
+ emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
}
void Assembler::xabort(int8_t imm8) {
@@ -3664,8 +3729,8 @@
void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
} else {
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
@@ -3684,8 +3749,8 @@
void Assembler::vaddss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F3, AVX_128bit);
}
@@ -3698,8 +3763,8 @@
void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
} else {
emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
@@ -3718,8 +3783,8 @@
void Assembler::vdivss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F3, AVX_128bit);
}
@@ -3732,8 +3797,8 @@
void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
} else {
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
@@ -3752,8 +3817,8 @@
void Assembler::vmulss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F3, AVX_128bit);
}
@@ -3766,8 +3831,8 @@
void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
} else {
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
@@ -3786,8 +3851,8 @@
void Assembler::vsubss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F3, AVX_128bit);
}
@@ -3802,6 +3867,7 @@
// Float-point vector arithmetic
void Assembler::addpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0x58, dst, src, VEX_SIMD_66);
@@ -3811,11 +3877,13 @@
}
void Assembler::addps(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x58, dst, src, VEX_SIMD_NONE);
}
void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3825,15 +3893,17 @@
}
void Assembler::vaddps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3841,15 +3911,17 @@
}
void Assembler::vaddps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::subpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_66);
@@ -3859,11 +3931,13 @@
}
void Assembler::subps(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x5C, dst, src, VEX_SIMD_NONE);
}
void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3873,15 +3947,17 @@
}
void Assembler::vsubps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3889,15 +3965,17 @@
}
void Assembler::vsubps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::mulpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0x59, dst, src, VEX_SIMD_66);
@@ -3907,11 +3985,13 @@
}
void Assembler::mulps(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x59, dst, src, VEX_SIMD_NONE);
}
void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3921,15 +4001,17 @@
}
void Assembler::vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3937,15 +4019,17 @@
}
void Assembler::vmulps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::divpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0x5E, dst, src, VEX_SIMD_66);
@@ -3955,11 +4039,13 @@
}
void Assembler::divps(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x5E, dst, src, VEX_SIMD_NONE);
}
void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3969,15 +4055,17 @@
}
void Assembler::vdivps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3985,164 +4073,178 @@
}
void Assembler::vdivps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(VM_Version::supports_avx(), "");
+ if (VM_Version::supports_evex()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector_len);
+}
+
+void Assembler::vsqrtpd(XMMRegister dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector_len);
+ emit_vex_arith_q(0x51, dst, xnoreg, src, VEX_SIMD_66, vector_len);
+ } else {
+ emit_vex_arith(0x51, dst, xnoreg, src, VEX_SIMD_66, vector_len);
+ }
+}
+
+void Assembler::vsqrtpd(XMMRegister dst, Address src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(VM_Version::supports_avx(), "");
+ if (VM_Version::supports_evex()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
+ emit_vex_arith_q(0x51, dst, xnoreg, src, VEX_SIMD_66, vector_len);
+ } else {
+ emit_vex_arith(0x51, dst, xnoreg, src, VEX_SIMD_66, vector_len);
+ }
}
void Assembler::andpd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
+ if (VM_Version::supports_avx512dq()) {
emit_simd_arith_q(0x54, dst, src, VEX_SIMD_66);
} else {
- emit_simd_arith(0x54, dst, src, VEX_SIMD_66, false, true);
+ emit_simd_arith(0x54, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::andps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE, false,
- (VM_Version::supports_avx512dq() == false));
+ emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::andps(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE,
- false, (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::andpd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ if (VM_Version::supports_avx512dq()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x54, dst, src, VEX_SIMD_66);
} else {
- emit_simd_arith(0x54, dst, src, VEX_SIMD_66, false, true);
+ emit_simd_arith(0x54, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
+ if (VM_Version::supports_avx512dq()) {
emit_vex_arith_q(0x54, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
- emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, true);
+ emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- bool legacy_mode = (VM_Version::supports_avx512dq() == false);
- emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, legacy_mode);
+ emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::vandpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ if (VM_Version::supports_avx512dq()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x54, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
- emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, true);
+ emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vandps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len,
- (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
+ if (VM_Version::supports_avx512dq()) {
emit_simd_arith_q(0x57, dst, src, VEX_SIMD_66);
} else {
- emit_simd_arith(0x57, dst, src, VEX_SIMD_66, false, true);
+ emit_simd_arith(0x57, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::xorps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE,
- false, (VM_Version::supports_avx512dq() == false));
+ emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::xorpd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ if (VM_Version::supports_avx512dq()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x57, dst, src, VEX_SIMD_66);
} else {
- emit_simd_arith(0x57, dst, src, VEX_SIMD_66, false, true);
+ emit_simd_arith(0x57, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::xorps(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE, false,
- (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
+ if (VM_Version::supports_avx512dq()) {
emit_vex_arith_q(0x57, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
- emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, true);
+ emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len,
- (VM_Version::supports_avx512dq() == false));
+ emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ if (VM_Version::supports_avx512dq()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x57, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
- emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, true);
+ emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vxorps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len,
- (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
// Integer vector arithmetic
void Assembler::vphaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx() && (vector_len == 0) ||
VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2");
- int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len,
- VEX_OPCODE_0F_38, true, false);
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38, /* legacy_mode */ true);
emit_int8(0x01);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -4150,28 +4252,29 @@
void Assembler::vphaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx() && (vector_len == 0) ||
VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2");
- int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len,
- VEX_OPCODE_0F_38, true, false);
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38, /* legacy_mode */ true);
emit_int8(0x02);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::paddb(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xFC, dst, src, VEX_SIMD_66);
+ emit_simd_arith(0xFC, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::paddw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xFD, dst, src, VEX_SIMD_66);
+ emit_simd_arith(0xFD, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::paddd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xFE, dst, src, VEX_SIMD_66);
}
void Assembler::paddq(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0xD4, dst, src, VEX_SIMD_66);
@@ -4182,38 +4285,38 @@
void Assembler::phaddw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse3(), ""));
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x01);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::phaddd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse3(), ""));
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x02);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0xD4, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -4225,33 +4328,35 @@
void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len);
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len);
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0xD4, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0xD4, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -4260,20 +4365,22 @@
void Assembler::psubb(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xF8, dst, src, VEX_SIMD_66);
+ emit_simd_arith(0xF8, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::psubw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xF9, dst, src, VEX_SIMD_66);
+ emit_simd_arith(0xF9, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::psubd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xFA, dst, src, VEX_SIMD_66);
}
void Assembler::psubq(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0xFB, dst, src, VEX_SIMD_66);
@@ -4284,22 +4391,22 @@
void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0xFB, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -4311,35 +4418,35 @@
void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0xFB, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0xFB, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -4348,28 +4455,27 @@
void Assembler::pmullw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xD5, dst, src, VEX_SIMD_66,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith(0xD5, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::pmulld(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_sse4_1(), "");
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66,
- false, VEX_OPCODE_0F_38);
+ /* no_mask_reg */ false, VEX_OPCODE_0F_38);
emit_int8(0x40);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
- int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38);
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x40);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -4379,8 +4485,8 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
- int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66,
- VEX_OPCODE_0F_38, true, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ true, vector_len, /* legacy_mode */ _legacy_mode_dq, /* no_mask_reg */ false);
emit_int8(0x40);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -4388,22 +4494,23 @@
void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len);
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
InstructionMark im(this);
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len);
+ VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x40);
emit_operand(dst, src);
}
@@ -4411,13 +4518,14 @@
void Assembler::vpmullq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
}
InstructionMark im(this);
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
- vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, true, vector_len);
+ vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66,
+ VEX_OPCODE_0F_38, /* vex_w */ true, vector_len, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x40);
emit_operand(dst, src);
}
@@ -4426,26 +4534,28 @@
void Assembler::psllw(XMMRegister dst, int shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM6 is for /6 encoding: 66 0F 71 /6 ib
- int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F,
- false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F,
+ /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x71);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::pslld(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM6 is for /6 encoding: 66 0F 72 /6 ib
- int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false);
+ int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false);
emit_int8(0x72);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::psllq(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM6 is for /6 encoding: 66 0F 73 /6 ib
- int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ true);
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
@@ -4453,16 +4563,17 @@
void Assembler::psllw(XMMRegister dst, XMMRegister shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xF1, dst, shift, VEX_SIMD_66, false,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith(0xF1, dst, shift, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::pslld(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xF2, dst, shift, VEX_SIMD_66);
}
void Assembler::psllq(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0xF3, dst, shift, VEX_SIMD_66);
@@ -4474,12 +4585,12 @@
void Assembler::vpsllw(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
// XMM6 is for /6 encoding: 66 0F 71 /6 ib
- emit_vex_arith(0x71, xmm6, dst, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0x71, xmm6, dst, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
emit_int8(shift & 0xFF);
}
void Assembler::vpslld(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
// XMM6 is for /6 encoding: 66 0F 72 /6 ib
emit_vex_arith(0x72, xmm6, dst, src, VEX_SIMD_66, vector_len);
@@ -4487,6 +4598,7 @@
}
void Assembler::vpsllq(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
// XMM6 is for /6 encoding: 66 0F 73 /6 ib
if (VM_Version::supports_evex()) {
@@ -4499,16 +4611,17 @@
void Assembler::vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xF1, dst, src, shift, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xF1, dst, src, shift, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xF2, dst, src, shift, VEX_SIMD_66, vector_len);
}
void Assembler::vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0xF3, dst, src, shift, VEX_SIMD_66, vector_len);
@@ -4521,33 +4634,31 @@
void Assembler::psrlw(XMMRegister dst, int shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM2 is for /2 encoding: 66 0F 71 /2 ib
- int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F,
- (VM_Version::supports_avx512bw() == false));
+ int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x71);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::psrld(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM2 is for /2 encoding: 66 0F 72 /2 ib
- int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false);
+ int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false);
emit_int8(0x72);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::psrlq(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
// Do not confuse it with psrldq SSE2 instruction which
// shifts 128 bit value in xmm register by number of bytes.
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM2 is for /2 encoding: 66 0F 73 /2 ib
- int encode = 0;
- if (VM_Version::supports_evex() && VM_Version::supports_avx512bw()) {
- encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false);
- } else {
- encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, true);
- }
+ int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F, /* rex_w */ VM_Version::supports_evex());
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
@@ -4555,16 +4666,17 @@
void Assembler::psrlw(XMMRegister dst, XMMRegister shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xD1, dst, shift, VEX_SIMD_66, false,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith(0xD1, dst, shift, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::psrld(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xD2, dst, shift, VEX_SIMD_66);
}
void Assembler::psrlq(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0xD3, dst, shift, VEX_SIMD_66);
@@ -4575,20 +4687,21 @@
void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- // XMM2 is for /2 encoding: 66 0F 73 /2 ib
- emit_vex_arith(0x71, xmm2, dst, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ // XMM2 is for /2 encoding: 66 0F 71 /2 ib
+ emit_vex_arith(0x71, xmm2, dst, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
emit_int8(shift & 0xFF);
}
void Assembler::vpsrld(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
- // XMM2 is for /2 encoding: 66 0F 73 /2 ib
+ // XMM2 is for /2 encoding: 66 0F 72 /2 ib
emit_vex_arith(0x72, xmm2, dst, src, VEX_SIMD_66, vector_len);
emit_int8(shift & 0xFF);
}
void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
// XMM2 is for /2 encoding: 66 0F 73 /2 ib
if (VM_Version::supports_evex()) {
@@ -4601,16 +4714,17 @@
void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xD1, dst, src, shift, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xD1, dst, src, shift, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xD2, dst, src, shift, VEX_SIMD_66, vector_len);
}
void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0xD3, dst, src, shift, VEX_SIMD_66, vector_len);
@@ -4623,17 +4737,18 @@
void Assembler::psraw(XMMRegister dst, int shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM4 is for /4 encoding: 66 0F 71 /4 ib
- int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F,
- (VM_Version::supports_avx512bw() == false));
+ int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x71);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::psrad(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM4 is for /4 encoding: 66 0F 72 /4 ib
- int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, false);
+ int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false);
emit_int8(0x72);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
@@ -4641,11 +4756,11 @@
void Assembler::psraw(XMMRegister dst, XMMRegister shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xE1, dst, shift, VEX_SIMD_66,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith(0xE1, dst, shift, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::psrad(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xE2, dst, shift, VEX_SIMD_66);
}
@@ -4653,12 +4768,12 @@
void Assembler::vpsraw(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
// XMM4 is for /4 encoding: 66 0F 71 /4 ib
- emit_vex_arith(0x71, xmm4, dst, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0x71, xmm4, dst, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
emit_int8(shift & 0xFF);
}
void Assembler::vpsrad(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
// XMM4 is for /4 encoding: 66 0F 71 /4 ib
emit_vex_arith(0x72, xmm4, dst, src, VEX_SIMD_66, vector_len);
@@ -4667,11 +4782,11 @@
void Assembler::vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xE1, dst, src, shift, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xE1, dst, src, shift, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xE2, dst, src, shift, VEX_SIMD_66, vector_len);
}
@@ -4684,53 +4799,61 @@
}
void Assembler::vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpand(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::por(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xEB, dst, src, VEX_SIMD_66);
}
void Assembler::vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::pxor(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xEF, dst, src, VEX_SIMD_66);
}
void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector_len);
}
@@ -4739,6 +4862,9 @@
void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
int vector_len = AVX_256bit;
+ if (VM_Version::supports_evex()) {
+ vector_len = AVX_512bit;
+ }
int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A);
emit_int8(0x18);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4753,8 +4879,8 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
- int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66,
- VEX_OPCODE_0F_3A, true, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x1A);
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - insert into lower 256 bits
@@ -4763,35 +4889,70 @@
}
void Assembler::vinsertf64x4h(XMMRegister dst, Address src) {
- assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_64bit;
- }
+ assert(VM_Version::supports_evex(), "");
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_64bit;
InstructionMark im(this);
int vector_len = AVX_512bit;
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ true, vector_len);
emit_int8(0x1A);
emit_operand(dst, src);
// 0x01 - insert into upper 128 bits
emit_int8(0x01);
}
+void Assembler::vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) {
+ assert(VM_Version::supports_evex(), "");
+ int vector_len = AVX_512bit;
+ int src_enc = src->encoding();
+ int dst_enc = dst->encoding();
+ int nds_enc = nds->is_valid() ? nds->encoding() : 0;
+ int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
+ emit_int8(0x18);
+ emit_int8((unsigned char)(0xC0 | encode));
+ // 0x00 - insert into q0 128 bits (0..127)
+ // 0x01 - insert into q1 128 bits (128..255)
+ // 0x02 - insert into q2 128 bits (256..383)
+ // 0x03 - insert into q3 128 bits (384..511)
+ emit_int8(value & 0x3);
+}
+
+void Assembler::vinsertf32x4h(XMMRegister dst, Address src, int value) {
+ assert(VM_Version::supports_evex(), "");
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ InstructionMark im(this);
+ int vector_len = AVX_512bit;
+ assert(dst != xnoreg, "sanity");
+ int dst_enc = dst->encoding();
+ // swap src<->dst for encoding
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
+ emit_int8(0x18);
+ emit_operand(dst, src);
+ // 0x00 - insert into q0 128 bits (0..127)
+ // 0x01 - insert into q1 128 bits (128..255)
+ // 0x02 - insert into q2 128 bits (256..383)
+ // 0x03 - insert into q3 128 bits (384..511)
+ emit_int8(value & 0x3);
+}
+
void Assembler::vinsertf128h(XMMRegister dst, Address src) {
assert(VM_Version::supports_avx(), "");
+ int vector_len = AVX_256bit;
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- int vector_len = AVX_256bit;
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ vector_len = AVX_512bit;
+ }
+ InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
emit_int8(0x18);
emit_operand(dst, src);
// 0x01 - insert into upper 128 bits
@@ -4801,6 +4962,9 @@
void Assembler::vextractf128h(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
int vector_len = AVX_256bit;
+ if (VM_Version::supports_evex()) {
+ vector_len = AVX_512bit;
+ }
int encode = vex_prefix_and_encode(src, xnoreg, dst, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4811,15 +4975,16 @@
void Assembler::vextractf128h(Address dst, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
+ int vector_len = AVX_256bit;
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- int vector_len = AVX_256bit;
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ vector_len = AVX_512bit;
+ }
+ InstructionMark im(this);
assert(src != xnoreg, "sanity");
int src_enc = src->encoding();
- vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len);
+ vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
emit_int8(0x19);
emit_operand(src, dst);
// 0x01 - extract from upper 128 bits
@@ -4829,6 +4994,9 @@
void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx2(), "");
int vector_len = AVX_256bit;
+ if (VM_Version::supports_evex()) {
+ vector_len = AVX_512bit;
+ }
int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A);
emit_int8(0x38);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4844,7 +5012,7 @@
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len, false, false);
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_reg_mask */ false);
emit_int8(0x38);
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - insert into lower 256 bits
@@ -4854,16 +5022,17 @@
void Assembler::vinserti128h(XMMRegister dst, Address src) {
assert(VM_Version::supports_avx2(), "");
+ int vector_len = AVX_256bit;
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- int vector_len = AVX_256bit;
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ vector_len = AVX_512bit;
+ }
+ InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
emit_int8(0x38);
emit_operand(dst, src);
// 0x01 - insert into upper 128 bits
@@ -4873,6 +5042,9 @@
void Assembler::vextracti128h(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
int vector_len = AVX_256bit;
+ if (VM_Version::supports_evex()) {
+ vector_len = AVX_512bit;
+ }
int encode = vex_prefix_and_encode(src, xnoreg, dst, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A);
emit_int8(0x39);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4883,15 +5055,16 @@
void Assembler::vextracti128h(Address dst, XMMRegister src) {
assert(VM_Version::supports_avx2(), "");
+ int vector_len = AVX_256bit;
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- int vector_len = AVX_256bit;
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ vector_len = AVX_512bit;
+ }
+ InstructionMark im(this);
assert(src != xnoreg, "sanity");
int src_enc = src->encoding();
- vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len);
+ vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
emit_int8(0x39);
emit_operand(src, dst);
// 0x01 - extract from upper 128 bits
@@ -4904,7 +5077,7 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- true, vector_len, false, false);
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x3B);
emit_int8((unsigned char)(0xC0 | encode));
// 0x01 - extract from upper 256 bits
@@ -4916,8 +5089,14 @@
int vector_len = AVX_512bit;
int src_enc = src->encoding();
int dst_enc = dst->encoding();
- int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len, false, false);
+ int encode;
+ if (VM_Version::supports_avx512dq()) {
+ encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
+ } else {
+ encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ false, vector_len, /* legacy_mode */ true, /* no_mask_reg */ false);
+ }
emit_int8(0x39);
emit_int8((unsigned char)(0xC0 | encode));
// 0x01 - extract from bits 255:128
@@ -4932,7 +5111,7 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len, false, false);
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x1B);
emit_int8((unsigned char)(0xC0 | encode));
// 0x01 - extract from upper 256 bits
@@ -4940,18 +5119,18 @@
}
void Assembler::vextractf64x4h(Address dst, XMMRegister src) {
- assert(VM_Version::supports_avx2(), "");
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_64bit;
+ assert(VM_Version::supports_evex(), "");
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_64bit;
InstructionMark im(this);
int vector_len = AVX_512bit;
assert(src != xnoreg, "sanity");
int src_enc = src->encoding();
vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len);
+ /* vex_w */ true, vector_len);
emit_int8(0x1B);
emit_operand(src, dst);
- // 0x01 - extract from upper 128 bits
+ // 0x01 - extract from upper 256 bits
emit_int8(0x01);
}
@@ -4960,10 +5139,29 @@
int vector_len = AVX_512bit;
int src_enc = src->encoding();
int dst_enc = dst->encoding();
- int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66,
- VEX_OPCODE_0F_3A, false, vector_len, false, false);
+ int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
+ // 0x00 - extract from bits 127:0
+ // 0x01 - extract from bits 255:128
+ // 0x02 - extract from bits 383:256
+ // 0x03 - extract from bits 511:384
+ emit_int8(value & 0x3);
+}
+
+void Assembler::vextractf32x4h(Address dst, XMMRegister src, int value) {
+ assert(VM_Version::supports_evex(), "");
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ InstructionMark im(this);
+ int vector_len = AVX_512bit;
+ assert(src != xnoreg, "sanity");
+ int src_enc = src->encoding();
+ vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
+ emit_int8(0x19);
+ emit_operand(src, dst);
+ // 0x00 - extract from bits 127:0
// 0x01 - extract from bits 255:128
// 0x02 - extract from bits 383:256
// 0x03 - extract from bits 511:384
@@ -4976,7 +5174,7 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len, false, false);
+ /* vex_w */ !_legacy_mode_dq, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
// 0x01 - extract from bits 255:128
@@ -4987,178 +5185,190 @@
// duplicate 4-bytes integer data from src into 8 locations in dest
void Assembler::vpbroadcastd(XMMRegister dst, XMMRegister src) {
- assert(VM_Version::supports_avx2(), "");
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
int vector_len = AVX_256bit;
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, false);
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x58);
emit_int8((unsigned char)(0xC0 | encode));
}
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x78);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastb(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_8bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_8bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x78);
emit_operand(dst, src);
}
// duplicate 2-byte integer data from src into 8|16||32 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastw(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x79);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastw(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_16bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_16bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x79);
emit_operand(dst, src);
}
// duplicate 4-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastd(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x58);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastd(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x58);
emit_operand(dst, src);
}
// duplicate 8-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastq(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, true, vector_len, false, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x59);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastq(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, true, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ true, vector_len);
emit_int8(0x59);
emit_operand(dst, src);
}
// duplicate single precision fp from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastss(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len, false, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x18);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastss(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
+ vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x18);
emit_operand(dst, src);
}
// duplicate double precision fp from src into 2|4|8 locations in dest : requires AVX512VL
void Assembler::evpbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, true, vector_len, false, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /*vex_w */ true, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastsd(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, true, vector_len);
+ vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ true, vector_len);
emit_int8(0x19);
emit_operand(dst, src);
}
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastb(XMMRegister dst, Register src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /*vex_w */ false, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x7A);
emit_int8((unsigned char)(0xC0 | encode));
}
// duplicate 2-byte integer data from src into 8|16||32 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastw(XMMRegister dst, Register src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x7B);
emit_int8((unsigned char)(0xC0 | encode));
}
// duplicate 4-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastd(XMMRegister dst, Register src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x7C);
emit_int8((unsigned char)(0xC0 | encode));
}
// duplicate 8-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastq(XMMRegister dst, Register src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, true, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x7C);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -5166,8 +5376,8 @@
// Carry-Less Multiplication Quadword
void Assembler::pclmulqdq(XMMRegister dst, XMMRegister src, int mask) {
assert(VM_Version::supports_clmul(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_3A, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_3A, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x44);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8((unsigned char)mask);
@@ -5177,8 +5387,7 @@
void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask) {
assert(VM_Version::supports_avx() && VM_Version::supports_clmul(), "");
int vector_len = AVX_128bit;
- int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_3A, true);
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A, /* legacy_mode */ true);
emit_int8(0x44);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8((unsigned char)mask);
@@ -5737,7 +5946,7 @@
int vector_len, bool no_mask_reg ){
// EVEX 0x62 prefix
prefix(EVEX_4bytes);
- evex_encoding = (vex_w ? VEX_W : 0) | (evex_r ? EVEX_Rb : 0);
+ _evex_encoding = (vex_w ? VEX_W : 0) | (evex_r ? EVEX_Rb : 0);
// P0: byte 2, initialized to RXBR`00mm
// instead of not'd
@@ -5776,10 +5985,10 @@
bool vex_r = ((xreg_enc & 8) == 8) ? 1 : 0;
bool vex_b = adr.base_needs_rex();
bool vex_x = adr.index_needs_rex();
- avx_vector_len = vector_len;
-
- // if vector length is turned off, revert to AVX for vectors smaller than AVX_512bit
- if (VM_Version::supports_avx512vl() == false) {
+ _avx_vector_len = vector_len;
+
+ // if vector length is turned off, revert to AVX for vectors smaller than 512-bit
+ if (_legacy_mode_vl && _instruction_uses_vl) {
switch (vector_len) {
case AVX_128bit:
case AVX_256bit:
@@ -5792,11 +6001,12 @@
{
bool evex_r = (xreg_enc >= 16);
bool evex_v = (nds_enc >= 16);
- is_evex_instruction = true;
+ _is_evex_instruction = true;
evex_prefix(vex_r, vex_b, vex_x, vex_w, evex_r, evex_v, nds_enc, pre, opc, false, false, vector_len, no_mask_reg);
} else {
vex_prefix(vex_r, vex_b, vex_x, vex_w, nds_enc, pre, opc, vector_len);
}
+ _instruction_uses_vl = false;
}
int Assembler::vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc,
@@ -5804,10 +6014,10 @@
bool vex_r = ((dst_enc & 8) == 8) ? 1 : 0;
bool vex_b = ((src_enc & 8) == 8) ? 1 : 0;
bool vex_x = false;
- avx_vector_len = vector_len;
-
- // if vector length is turned off, revert to AVX for vectors smaller than AVX_512bit
- if (VM_Version::supports_avx512vl() == false) {
+ _avx_vector_len = vector_len;
+
+ // if vector length is turned off, revert to AVX for vectors smaller than 512-bit
+ if (_legacy_mode_vl && _instruction_uses_vl) {
switch (vector_len) {
case AVX_128bit:
case AVX_256bit:
@@ -5827,6 +6037,8 @@
vex_prefix(vex_r, vex_b, vex_x, vex_w, nds_enc, pre, opc, vector_len);
}
+ _instruction_uses_vl = false;
+
// return modrm byte components for operands
return (((dst_enc & 7) << 3) | (src_enc & 7));
}
@@ -5915,13 +6127,13 @@
}
void Assembler::emit_simd_arith_nonds(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg, bool legacy_mode) {
- int encode = simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg, VEX_OPCODE_0F, legacy_mode, AVX_128bit);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg, VEX_OPCODE_0F, false, AVX_128bit, legacy_mode);
emit_int8(opcode);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::emit_simd_arith_nonds_q(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg) {
- int encode = simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg, VEX_OPCODE_0F, true, AVX_128bit);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg, VEX_OPCODE_0F, true);
emit_int8(opcode);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -5945,7 +6157,7 @@
void Assembler::emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src,
VexSimdPrefix pre, int vector_len, bool no_mask_reg, bool legacy_mode) {
- int encode = vex_prefix_and_encode(dst, nds, src, pre, vector_len, VEX_OPCODE_0F, false, no_mask_reg);
+ int encode = vex_prefix_and_encode(dst, nds, src, pre, vector_len, VEX_OPCODE_0F, legacy_mode, no_mask_reg);
emit_int8(opcode);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6594,7 +6806,7 @@
void Assembler::cvtsi2sdq(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F2, true);
+ int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6602,11 +6814,11 @@
void Assembler::cvtsi2sdq(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix_q(dst, dst, src, VEX_SIMD_F2, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix_q(dst, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_operand(dst, src);
}
@@ -6614,25 +6826,25 @@
void Assembler::cvtsi2ssq(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix_q(dst, dst, src, VEX_SIMD_F3, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix_q(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_operand(dst, src);
}
void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, /* no_mask_reg */ true);
emit_int8(0x2C);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::cvttss2siq(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, /* no_mask_reg */ true);
emit_int8(0x2C);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6668,6 +6880,13 @@
emit_operand(as_Register(1), src);
}
+void Assembler::xrstor(Address src) {
+ prefixq(src);
+ emit_int8(0x0F);
+ emit_int8((unsigned char)0xAE);
+ emit_operand(as_Register(5), src);
+}
+
void Assembler::fxsave(Address dst) {
prefixq(dst);
emit_int8(0x0F);
@@ -6675,6 +6894,13 @@
emit_operand(as_Register(0), dst);
}
+void Assembler::xsave(Address dst) {
+ prefixq(dst);
+ emit_int8(0x0F);
+ emit_int8((unsigned char)0xAE);
+ emit_operand(as_Register(4), dst);
+}
+
void Assembler::idivq(Register src) {
int encode = prefixq_and_encode(src->encoding());
emit_int8((unsigned char)0xF7);
@@ -6801,7 +7027,7 @@
void Assembler::movdq(XMMRegister dst, Register src) {
// table D-1 says MMX/SSE2
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_66, true);
+ int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
emit_int8(0x6E);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6810,7 +7036,7 @@
// table D-1 says MMX/SSE2
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// swap src/dst to get correct prefix
- int encode = simd_prefix_and_encode_q(src, dst, VEX_SIMD_66, true);
+ int encode = simd_prefix_and_encode_q(src, dst, VEX_SIMD_66, /* no_mask_reg */ true);
emit_int8(0x7E);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6943,8 +7169,8 @@
void Assembler::mulxq(Register dst1, Register dst2, Register src) {
assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
- int encode = vex_prefix_and_encode(dst1->encoding(), dst2->encoding(), src->encoding(),
- VEX_SIMD_F2, VEX_OPCODE_0F_38, true, AVX_128bit, true, false);
+ int encode = vex_prefix_and_encode(dst1->encoding(), dst2->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38,
+ /* vex_w */ true, AVX_128bit, /* legacy_mode */ true, /* no_mask_reg */ false);
emit_int8((unsigned char)0xF6);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -7106,8 +7332,8 @@
void Assembler::rorxq(Register dst, Register src, int imm8) {
assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2,
- VEX_OPCODE_0F_3A, true, AVX_128bit, true, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_3A,
+ /* vex_w */ true, AVX_128bit, /* legacy_mode */ true, /* no_mask_reg */ false);
emit_int8((unsigned char)0xF0);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -438,7 +438,9 @@
};
-const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY( 512*2 / wordSize);
+// 64-bit refect the fxsave size which is 512 bytes and the new xsave area on EVEX which is another 2176 bytes
+// See fxsave and xsave(EVEX enabled) documentation for layout
+const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY(2688 / wordSize);
// The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction
// level (e.g. mov rax, 0 is not translated into xor rax, rax!); i.e., what you write
@@ -594,11 +596,16 @@
private:
- int evex_encoding;
- int input_size_in_bits;
- int avx_vector_len;
- int tuple_type;
- bool is_evex_instruction;
+ int _evex_encoding;
+ int _input_size_in_bits;
+ int _avx_vector_len;
+ int _tuple_type;
+ bool _is_evex_instruction;
+ bool _legacy_mode_bw;
+ bool _legacy_mode_dq;
+ bool _legacy_mode_vl;
+ bool _legacy_mode_vlbw;
+ bool _instruction_uses_vl;
// 64bit prefixes
int prefix_and_encode(int reg_enc, bool byteinst = false);
@@ -972,11 +979,16 @@
// belong in macro assembler but there is no need for both varieties to exist
void init_attributes(void) {
- evex_encoding = 0;
- input_size_in_bits = 0;
- avx_vector_len = AVX_NoVec;
- tuple_type = EVEX_ETUP;
- is_evex_instruction = false;
+ _evex_encoding = 0;
+ _input_size_in_bits = 0;
+ _avx_vector_len = AVX_NoVec;
+ _tuple_type = EVEX_ETUP;
+ _is_evex_instruction = false;
+ _legacy_mode_bw = (VM_Version::supports_avx512bw() == false);
+ _legacy_mode_dq = (VM_Version::supports_avx512dq() == false);
+ _legacy_mode_vl = (VM_Version::supports_avx512vl() == false);
+ _legacy_mode_vlbw = (VM_Version::supports_avx512vlbw() == false);
+ _instruction_uses_vl = false;
}
void lea(Register dst, Address src);
@@ -1344,8 +1356,10 @@
void fxch(int i = 1);
void fxrstor(Address src);
+ void xrstor(Address src);
void fxsave(Address dst);
+ void xsave(Address dst);
void fyl2x();
void frndint();
@@ -1479,11 +1493,12 @@
void movb(Address dst, int imm8);
void movb(Register dst, Address src);
- void kmovq(KRegister dst, KRegister src);
+ void kmovql(KRegister dst, KRegister src);
void kmovql(KRegister dst, Register src);
void kmovdl(KRegister dst, Register src);
- void kmovq(Address dst, KRegister src);
- void kmovq(KRegister dst, Address src);
+ void kmovwl(KRegister dst, Register src);
+ void kmovql(Address dst, KRegister src);
+ void kmovql(KRegister dst, Address src);
void movdl(XMMRegister dst, Register src);
void movdl(Register dst, XMMRegister src);
@@ -1509,9 +1524,12 @@
void vmovdqu(XMMRegister dst, XMMRegister src);
// Move Unaligned 512bit Vector
- void evmovdqu(Address dst, XMMRegister src, int vector_len);
- void evmovdqu(XMMRegister dst, Address src, int vector_len);
- void evmovdqu(XMMRegister dst, XMMRegister src, int vector_len);
+ void evmovdqul(Address dst, XMMRegister src, int vector_len);
+ void evmovdqul(XMMRegister dst, Address src, int vector_len);
+ void evmovdqul(XMMRegister dst, XMMRegister src, int vector_len);
+ void evmovdquq(Address dst, XMMRegister src, int vector_len);
+ void evmovdquq(XMMRegister dst, Address src, int vector_len);
+ void evmovdquq(XMMRegister dst, XMMRegister src, int vector_len);
// Move lower 64bit to high 64bit in 128bit register
void movlhps(XMMRegister dst, XMMRegister src);
@@ -1643,6 +1661,7 @@
// Pemutation of 64bit words
void vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len);
+ void vpermq(XMMRegister dst, XMMRegister src, int imm8);
void pause();
@@ -1920,6 +1939,10 @@
void vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vdivps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
+ // Sqrt Packed Floating-Point Values - Double precision only
+ void vsqrtpd(XMMRegister dst, XMMRegister src, int vector_len);
+ void vsqrtpd(XMMRegister dst, Address src, int vector_len);
+
// Bitwise Logical AND of Packed Floating-Point Values
void andpd(XMMRegister dst, XMMRegister src);
void andps(XMMRegister dst, XMMRegister src);
@@ -2057,6 +2080,9 @@
void vextracti64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf32x4h(XMMRegister dst, XMMRegister src, int value);
+ void vextractf32x4h(Address dst, XMMRegister src, int value);
+ void vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value);
+ void vinsertf32x4h(XMMRegister dst, Address src, int value);
// duplicate 4-bytes integer data from src into 8 locations in dest
void vpbroadcastd(XMMRegister dst, XMMRegister src);
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -3798,16 +3798,24 @@
if (left->as_xmm_float_reg() != dest->as_xmm_float_reg()) {
__ movflt(dest->as_xmm_float_reg(), left->as_xmm_float_reg());
}
- __ xorps(dest->as_xmm_float_reg(),
- ExternalAddress((address)float_signflip_pool));
-
+ if (UseAVX > 1) {
+ __ vnegatess(dest->as_xmm_float_reg(), dest->as_xmm_float_reg(),
+ ExternalAddress((address)float_signflip_pool));
+ } else {
+ __ xorps(dest->as_xmm_float_reg(),
+ ExternalAddress((address)float_signflip_pool));
+ }
} else if (dest->is_double_xmm()) {
if (left->as_xmm_double_reg() != dest->as_xmm_double_reg()) {
__ movdbl(dest->as_xmm_double_reg(), left->as_xmm_double_reg());
}
- __ xorpd(dest->as_xmm_double_reg(),
- ExternalAddress((address)double_signflip_pool));
-
+ if (UseAVX > 1) {
+ __ vnegatesd(dest->as_xmm_double_reg(), dest->as_xmm_double_reg(),
+ ExternalAddress((address)double_signflip_pool));
+ } else {
+ __ xorpd(dest->as_xmm_double_reg(),
+ ExternalAddress((address)double_signflip_pool));
+ }
} else if (left->is_single_fpu() || left->is_double_fpu()) {
assert(left->fpu() == 0, "arg must be on TOS");
assert(dest->fpu() == 0, "dest must be TOS");
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -401,11 +401,9 @@
} else if (UseSSE == 1) {
int xmm_off = xmm_regs_as_doubles_off;
- for (int n = 0; n < FrameMap::nof_xmm_regs; n++) {
- if (n < xmm_bypass_limit) {
- VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
- map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
- }
+ for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
+ VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
+ map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
xmm_off += 2;
}
assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
@@ -452,14 +450,11 @@
__ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
// Save the FPU registers in de-opt-able form
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
+ int offset = 0;
+ for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
+ __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
+ offset += 8;
+ }
}
if (UseSSE >= 2) {
@@ -468,52 +463,26 @@
// so always save them as doubles.
// note that float values are _not_ converted automatically, so for float values
// the second word contains only garbage data.
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7);
+ int xmm_bypass_limit = FrameMap::nof_xmm_regs;
+ int offset = 0;
#ifdef _LP64
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64), xmm8);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72), xmm9);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80), xmm10);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88), xmm11);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96), xmm12);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104), xmm13);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112), xmm14);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120), xmm15);
- if (UseAVX > 2) {
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 128), xmm16);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 136), xmm17);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 144), xmm18);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 152), xmm19);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 160), xmm20);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 168), xmm21);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 176), xmm22);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 184), xmm23);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 192), xmm24);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 200), xmm25);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 208), xmm26);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 216), xmm27);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 224), xmm28);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 232), xmm29);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 240), xmm30);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 248), xmm31);
+ if (UseAVX < 3) {
+ xmm_bypass_limit = xmm_bypass_limit / 2;
+ }
+#endif
+ for (int n = 0; n < xmm_bypass_limit; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
+ offset += 8;
}
-#endif // _LP64
} else if (UseSSE == 1) {
- // save XMM registers as float because double not supported without SSE2
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7);
+ // save XMM registers as float because double not supported without SSE2(num MMX == num fpu)
+ int offset = 0;
+ for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
+ offset += 8;
+ }
}
}
@@ -528,52 +497,26 @@
if (restore_fpu_registers) {
if (UseSSE >= 2) {
// restore XMM registers
- __ movdbl(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
- __ movdbl(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
- __ movdbl(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
- __ movdbl(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
- __ movdbl(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
- __ movdbl(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
- __ movdbl(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
- __ movdbl(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
+ int xmm_bypass_limit = FrameMap::nof_xmm_regs;
#ifdef _LP64
- __ movdbl(xmm8, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64));
- __ movdbl(xmm9, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72));
- __ movdbl(xmm10, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80));
- __ movdbl(xmm11, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88));
- __ movdbl(xmm12, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96));
- __ movdbl(xmm13, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104));
- __ movdbl(xmm14, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112));
- __ movdbl(xmm15, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120));
- if (UseAVX > 2) {
- __ movdbl(xmm16, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 128));
- __ movdbl(xmm17, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 136));
- __ movdbl(xmm18, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 144));
- __ movdbl(xmm19, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 152));
- __ movdbl(xmm20, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 160));
- __ movdbl(xmm21, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 168));
- __ movdbl(xmm22, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 176));
- __ movdbl(xmm23, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 184));
- __ movdbl(xmm24, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 192));
- __ movdbl(xmm25, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 200));
- __ movdbl(xmm26, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 208));
- __ movdbl(xmm27, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 216));
- __ movdbl(xmm28, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 224));
- __ movdbl(xmm29, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 232));
- __ movdbl(xmm30, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 240));
- __ movdbl(xmm31, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 248));
+ if (UseAVX < 3) {
+ xmm_bypass_limit = xmm_bypass_limit / 2;
}
-#endif // _LP64
+#endif
+ int offset = 0;
+ for (int n = 0; n < xmm_bypass_limit; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ __ movdbl(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
+ offset += 8;
+ }
} else if (UseSSE == 1) {
- // restore XMM registers
- __ movflt(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
- __ movflt(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
- __ movflt(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
- __ movflt(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
- __ movflt(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
- __ movflt(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
- __ movflt(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
- __ movflt(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
+ // restore XMM registers(num MMX == num fpu)
+ int offset = 0;
+ for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ __ movflt(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
+ offset += 8;
+ }
}
if (UseSSE < 2) {
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -3751,8 +3751,31 @@
}
void MacroAssembler::pop_FPU_state() {
- NOT_LP64(frstor(Address(rsp, 0));)
- LP64_ONLY(fxrstor(Address(rsp, 0));)
+#ifndef _LP64
+ frstor(Address(rsp, 0));
+#else
+ // AVX will continue to use the fxsave area.
+ // EVEX needs to utilize the xsave area, which is under different
+ // management.
+ if(VM_Version::supports_evex()) {
+ // EDX:EAX describe the XSAVE header and
+ // are obtained while fetching info for XCR0 via cpuid.
+ // These two registers make up 64-bits in the header for which bits
+ // 62:10 are currently reserved for future implementations and unused. Bit 63
+ // is unused for our implementation as we do not utilize
+ // compressed XSAVE areas. Bits 9..8 are currently ignored as we do not use
+ // the functionality for PKRU state and MSR tracing.
+ // Ergo we are primarily concerned with bits 7..0, which define
+ // which ISA extensions and features are enabled for a given machine and are
+ // defined in XemXcr0Eax and is used to map the XSAVE area
+ // for restoring registers as described via XCR0.
+ movl(rdx,VM_Version::get_xsave_header_upper_segment());
+ movl(rax,VM_Version::get_xsave_header_lower_segment());
+ xrstor(Address(rsp, 0));
+ } else {
+ fxrstor(Address(rsp, 0));
+ }
+#endif
addptr(rsp, FPUStateSizeInWords * wordSize);
}
@@ -3769,13 +3792,49 @@
push_FPU_state();
}
+#ifdef _LP64
+#define XSTATE_BV 0x200
+#endif
+
void MacroAssembler::push_FPU_state() {
subptr(rsp, FPUStateSizeInWords * wordSize);
#ifndef _LP64
fnsave(Address(rsp, 0));
fwait();
#else
- fxsave(Address(rsp, 0));
+ // AVX will continue to use the fxsave area.
+ // EVEX needs to utilize the xsave area, which is under different
+ // management.
+ if(VM_Version::supports_evex()) {
+ // Save a copy of EAX and EDX
+ push(rax);
+ push(rdx);
+ // EDX:EAX describe the XSAVE header and
+ // are obtained while fetching info for XCR0 via cpuid.
+ // These two registers make up 64-bits in the header for which bits
+ // 62:10 are currently reserved for future implementations and unused. Bit 63
+ // is unused for our implementation as we do not utilize
+ // compressed XSAVE areas. Bits 9..8 are currently ignored as we do not use
+ // the functionality for PKRU state and MSR tracing.
+ // Ergo we are primarily concerned with bits 7..0, which define
+ // which ISA extensions and features are enabled for a given machine and are
+ // defined in XemXcr0Eax and is used to program XSAVE area
+ // for saving the required registers as defined in XCR0.
+ int xcr0_edx = VM_Version::get_xsave_header_upper_segment();
+ int xcr0_eax = VM_Version::get_xsave_header_lower_segment();
+ movl(rdx,xcr0_edx);
+ movl(rax,xcr0_eax);
+ xsave(Address(rsp, wordSize*2));
+ // now Apply control bits and clear bytes 8..23 in the header
+ pop(rdx);
+ pop(rax);
+ movl(Address(rsp, XSTATE_BV), xcr0_eax);
+ movl(Address(rsp, XSTATE_BV+4), xcr0_edx);
+ andq(Address(rsp, XSTATE_BV+8), 0);
+ andq(Address(rsp, XSTATE_BV+16), 0);
+ } else {
+ fxsave(Address(rsp, 0));
+ }
#endif // LP64
}
@@ -4082,6 +4141,84 @@
}
}
+void MacroAssembler::vnegatess(XMMRegister dst, XMMRegister nds, AddressLiteral src) {
+ int nds_enc = nds->encoding();
+ int dst_enc = dst->encoding();
+ bool dst_upper_bank = (dst_enc > 15);
+ bool nds_upper_bank = (nds_enc > 15);
+ if (VM_Version::supports_avx512novl() &&
+ (nds_upper_bank || dst_upper_bank)) {
+ if (dst_upper_bank) {
+ subptr(rsp, 64);
+ evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ movflt(xmm0, nds);
+ if (reachable(src)) {
+ vxorps(xmm0, xmm0, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(xmm0, xmm0, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ movflt(dst, xmm0);
+ evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
+ addptr(rsp, 64);
+ } else {
+ movflt(dst, nds);
+ if (reachable(src)) {
+ vxorps(dst, dst, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(dst, dst, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ }
+ } else {
+ if (reachable(src)) {
+ vxorps(dst, nds, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(dst, nds, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ }
+}
+
+void MacroAssembler::vnegatesd(XMMRegister dst, XMMRegister nds, AddressLiteral src) {
+ int nds_enc = nds->encoding();
+ int dst_enc = dst->encoding();
+ bool dst_upper_bank = (dst_enc > 15);
+ bool nds_upper_bank = (nds_enc > 15);
+ if (VM_Version::supports_avx512novl() &&
+ (nds_upper_bank || dst_upper_bank)) {
+ if (dst_upper_bank) {
+ subptr(rsp, 64);
+ evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ movdbl(xmm0, nds);
+ if (reachable(src)) {
+ vxorps(xmm0, xmm0, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(xmm0, xmm0, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ movdbl(dst, xmm0);
+ evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
+ addptr(rsp, 64);
+ } else {
+ movdbl(dst, nds);
+ if (reachable(src)) {
+ vxorps(dst, dst, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(dst, dst, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ }
+ } else {
+ if (reachable(src)) {
+ vxorpd(dst, nds, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorpd(dst, nds, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ }
+}
+
void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) {
if (reachable(src)) {
vxorpd(dst, nds, as_Address(src), vector_len);
@@ -4318,9 +4455,10 @@
void MacroAssembler::store_check(Register obj) {
// Does a store check for the oop in register obj. The content of
// register obj is destroyed afterwards.
-
BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
+ assert(bs->kind() == BarrierSet::CardTableForRS ||
+ bs->kind() == BarrierSet::CardTableExtension,
+ "Wrong barrier set kind");
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
@@ -4570,69 +4708,58 @@
// if we are coming from c1, xmm registers may be live
int off = 0;
+ int num_xmm_regs = LP64_ONLY(16) NOT_LP64(8);
+ if (UseAVX > 2) {
+ num_xmm_regs = LP64_ONLY(32) NOT_LP64(8);
+ }
+
if (UseSSE == 1) {
subptr(rsp, sizeof(jdouble)*8);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm0);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm1);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm2);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm3);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm4);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm5);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm6);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm7);
+ for (int n = 0; n < 8; n++) {
+ movflt(Address(rsp, off++*sizeof(jdouble)), as_XMMRegister(n));
+ }
} else if (UseSSE >= 2) {
if (UseAVX > 2) {
+ push(rbx);
movl(rbx, 0xffff);
-#ifdef _LP64
- kmovql(k1, rbx);
-#else
- kmovdl(k1, rbx);
-#endif
+ kmovwl(k1, rbx);
+ pop(rbx);
}
#ifdef COMPILER2
if (MaxVectorSize > 16) {
- assert(UseAVX > 0, "256bit vectors are supported only with AVX");
+ if(UseAVX > 2) {
+ // Save upper half of ZMM registes
+ subptr(rsp, 32*num_xmm_regs);
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vextractf64x4h(Address(rsp, off++*32), as_XMMRegister(n));
+ }
+ off = 0;
+ }
+ assert(UseAVX > 0, "256 bit vectors are supported only with AVX");
// Save upper half of YMM registes
- subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
- vextractf128h(Address(rsp, 0),xmm0);
- vextractf128h(Address(rsp, 16),xmm1);
- vextractf128h(Address(rsp, 32),xmm2);
- vextractf128h(Address(rsp, 48),xmm3);
- vextractf128h(Address(rsp, 64),xmm4);
- vextractf128h(Address(rsp, 80),xmm5);
- vextractf128h(Address(rsp, 96),xmm6);
- vextractf128h(Address(rsp,112),xmm7);
-#ifdef _LP64
- vextractf128h(Address(rsp,128),xmm8);
- vextractf128h(Address(rsp,144),xmm9);
- vextractf128h(Address(rsp,160),xmm10);
- vextractf128h(Address(rsp,176),xmm11);
- vextractf128h(Address(rsp,192),xmm12);
- vextractf128h(Address(rsp,208),xmm13);
- vextractf128h(Address(rsp,224),xmm14);
- vextractf128h(Address(rsp,240),xmm15);
-#endif
+ subptr(rsp, 16*num_xmm_regs);
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
+ }
}
#endif
- // Save whole 128bit (16 bytes) XMM regiters
- subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
- movdqu(Address(rsp,off++*16),xmm0);
- movdqu(Address(rsp,off++*16),xmm1);
- movdqu(Address(rsp,off++*16),xmm2);
- movdqu(Address(rsp,off++*16),xmm3);
- movdqu(Address(rsp,off++*16),xmm4);
- movdqu(Address(rsp,off++*16),xmm5);
- movdqu(Address(rsp,off++*16),xmm6);
- movdqu(Address(rsp,off++*16),xmm7);
+ // Save whole 128bit (16 bytes) XMM registers
+ subptr(rsp, 16*num_xmm_regs);
+ off = 0;
#ifdef _LP64
- movdqu(Address(rsp,off++*16),xmm8);
- movdqu(Address(rsp,off++*16),xmm9);
- movdqu(Address(rsp,off++*16),xmm10);
- movdqu(Address(rsp,off++*16),xmm11);
- movdqu(Address(rsp,off++*16),xmm12);
- movdqu(Address(rsp,off++*16),xmm13);
- movdqu(Address(rsp,off++*16),xmm14);
- movdqu(Address(rsp,off++*16),xmm15);
+ if (VM_Version::supports_avx512novl()) {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vextractf32x4h(Address(rsp, off++*16), as_XMMRegister(n), 0);
+ }
+ } else {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ movdqu(Address(rsp, off++*16), as_XMMRegister(n));
+ }
+ }
+#else
+ for (int n = 0; n < num_xmm_regs; n++) {
+ movdqu(Address(rsp, off++*16), as_XMMRegister(n));
+ }
#endif
}
@@ -4687,7 +4814,7 @@
movsd(Address(rsp, 0), xmm0);
fld_d(Address(rsp, 0));
#endif // _LP64
- addptr(rsp, sizeof(jdouble) * nb_args);
+ addptr(rsp, sizeof(jdouble)*nb_args);
if (num_fpu_regs_in_use > 1) {
// Must save return value to stack and then restore entire FPU
// stack except incoming arguments
@@ -4697,63 +4824,50 @@
addptr(rsp, sizeof(jdouble));
}
fld_d(Address(rsp, (nb_args-1)*sizeof(jdouble)));
- addptr(rsp, sizeof(jdouble) * nb_args);
+ addptr(rsp, sizeof(jdouble)*nb_args);
}
off = 0;
if (UseSSE == 1) {
- movflt(xmm0, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm1, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm2, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm3, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm4, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm5, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm6, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm7, Address(rsp,off++*sizeof(jdouble)));
+ for (int n = 0; n < 8; n++) {
+ movflt(as_XMMRegister(n), Address(rsp, off++*sizeof(jdouble)));
+ }
addptr(rsp, sizeof(jdouble)*8);
} else if (UseSSE >= 2) {
// Restore whole 128bit (16 bytes) XMM regiters
- movdqu(xmm0, Address(rsp,off++*16));
- movdqu(xmm1, Address(rsp,off++*16));
- movdqu(xmm2, Address(rsp,off++*16));
- movdqu(xmm3, Address(rsp,off++*16));
- movdqu(xmm4, Address(rsp,off++*16));
- movdqu(xmm5, Address(rsp,off++*16));
- movdqu(xmm6, Address(rsp,off++*16));
- movdqu(xmm7, Address(rsp,off++*16));
#ifdef _LP64
- movdqu(xmm8, Address(rsp,off++*16));
- movdqu(xmm9, Address(rsp,off++*16));
- movdqu(xmm10, Address(rsp,off++*16));
- movdqu(xmm11, Address(rsp,off++*16));
- movdqu(xmm12, Address(rsp,off++*16));
- movdqu(xmm13, Address(rsp,off++*16));
- movdqu(xmm14, Address(rsp,off++*16));
- movdqu(xmm15, Address(rsp,off++*16));
+ if (VM_Version::supports_avx512novl()) {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vinsertf32x4h(as_XMMRegister(n), Address(rsp, off++*16), 0);
+ }
+ }
+ else {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ movdqu(as_XMMRegister(n), Address(rsp, off++*16));
+ }
+ }
+#else
+ for (int n = 0; n < num_xmm_regs; n++) {
+ movdqu(as_XMMRegister(n), Address(rsp, off++ * 16));
+ }
#endif
- addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
+ addptr(rsp, 16*num_xmm_regs);
+
#ifdef COMPILER2
if (MaxVectorSize > 16) {
// Restore upper half of YMM registes.
- vinsertf128h(xmm0, Address(rsp, 0));
- vinsertf128h(xmm1, Address(rsp, 16));
- vinsertf128h(xmm2, Address(rsp, 32));
- vinsertf128h(xmm3, Address(rsp, 48));
- vinsertf128h(xmm4, Address(rsp, 64));
- vinsertf128h(xmm5, Address(rsp, 80));
- vinsertf128h(xmm6, Address(rsp, 96));
- vinsertf128h(xmm7, Address(rsp,112));
-#ifdef _LP64
- vinsertf128h(xmm8, Address(rsp,128));
- vinsertf128h(xmm9, Address(rsp,144));
- vinsertf128h(xmm10, Address(rsp,160));
- vinsertf128h(xmm11, Address(rsp,176));
- vinsertf128h(xmm12, Address(rsp,192));
- vinsertf128h(xmm13, Address(rsp,208));
- vinsertf128h(xmm14, Address(rsp,224));
- vinsertf128h(xmm15, Address(rsp,240));
-#endif
- addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
+ }
+ addptr(rsp, 16*num_xmm_regs);
+ if(UseAVX > 2) {
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vinsertf64x4h(as_XMMRegister(n), Address(rsp, off++*32));
+ }
+ addptr(rsp, 32*num_xmm_regs);
+ }
}
#endif
}
@@ -7093,11 +7207,7 @@
Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes;
if (UseAVX > 2) {
movl(rtmp, 0xffff);
-#ifdef _LP64
- kmovql(k1, rtmp);
-#else
- kmovdl(k1, rtmp);
-#endif
+ kmovwl(k1, rtmp);
}
movdl(xtmp, value);
if (UseAVX > 2 && UseUnalignedLoadStores) {
@@ -7110,7 +7220,7 @@
align(16);
BIND(L_fill_64_bytes_loop);
- evmovdqu(Address(to, 0), xtmp, Assembler::AVX_512bit);
+ evmovdqul(Address(to, 0), xtmp, Assembler::AVX_512bit);
addptr(to, 64);
subl(count, 16 << shift);
jcc(Assembler::greaterEqual, L_fill_64_bytes_loop);
@@ -7118,7 +7228,7 @@
BIND(L_check_fill_32_bytes);
addl(count, 8 << shift);
jccb(Assembler::less, L_check_fill_8_bytes);
- evmovdqu(Address(to, 0), xtmp, Assembler::AVX_256bit);
+ evmovdqul(Address(to, 0), xtmp, Assembler::AVX_256bit);
addptr(to, 32);
subl(count, 8 << shift);
@@ -8397,6 +8507,14 @@
Label L_tail, L_tail_restore, L_tail_loop, L_exit, L_align_loop, L_aligned;
Label L_fold_tail, L_fold_128b, L_fold_512b, L_fold_512b_loop, L_fold_tail_loop;
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ movl(tmp, 0xffff);
+ kmovwl(k1, tmp);
+ }
+
lea(table, ExternalAddress(StubRoutines::crc_table_addr()));
notl(crc); // ~crc
cmpl(len, 16);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -1069,6 +1069,9 @@
void vsubss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubss(dst, nds, src); }
void vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src);
+ void vnegatess(XMMRegister dst, XMMRegister nds, AddressLiteral src);
+ void vnegatesd(XMMRegister dst, XMMRegister nds, AddressLiteral src);
+
// AVX Vector instructions
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); }
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -115,6 +115,7 @@
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words,
int* total_frame_words, bool verify_fpu, bool save_vectors) {
int vect_words = 0;
+ int num_xmm_regs = XMMRegisterImpl::number_of_registers;
#ifdef COMPILER2
if (save_vectors) {
assert(UseAVX > 0, "512bit vectors are supported only with EVEX");
@@ -173,59 +174,50 @@
__ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
}
+ int off = st0_off;
+ int delta = st1_off - off;
+
// Save the FPU registers in de-opt-able form
-
- __ fstp_d(Address(rsp, st0_off*wordSize)); // st(0)
- __ fstp_d(Address(rsp, st1_off*wordSize)); // st(1)
- __ fstp_d(Address(rsp, st2_off*wordSize)); // st(2)
- __ fstp_d(Address(rsp, st3_off*wordSize)); // st(3)
- __ fstp_d(Address(rsp, st4_off*wordSize)); // st(4)
- __ fstp_d(Address(rsp, st5_off*wordSize)); // st(5)
- __ fstp_d(Address(rsp, st6_off*wordSize)); // st(6)
- __ fstp_d(Address(rsp, st7_off*wordSize)); // st(7)
-
- if( UseSSE == 1 ) { // Save the XMM state
- __ movflt(Address(rsp,xmm0_off*wordSize),xmm0);
- __ movflt(Address(rsp,xmm1_off*wordSize),xmm1);
- __ movflt(Address(rsp,xmm2_off*wordSize),xmm2);
- __ movflt(Address(rsp,xmm3_off*wordSize),xmm3);
- __ movflt(Address(rsp,xmm4_off*wordSize),xmm4);
- __ movflt(Address(rsp,xmm5_off*wordSize),xmm5);
- __ movflt(Address(rsp,xmm6_off*wordSize),xmm6);
- __ movflt(Address(rsp,xmm7_off*wordSize),xmm7);
- } else if( UseSSE >= 2 ) {
+ for (int n = 0; n < FloatRegisterImpl::number_of_registers; n++) {
+ __ fstp_d(Address(rsp, off*wordSize));
+ off += delta;
+ }
+
+ off = xmm0_off;
+ delta = xmm1_off - off;
+ if(UseSSE == 1) { // Save the XMM state
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ movflt(Address(rsp, off*wordSize), as_XMMRegister(n));
+ off += delta;
+ }
+ } else if(UseSSE >= 2) {
// Save whole 128bit (16 bytes) XMM regiters
- __ movdqu(Address(rsp,xmm0_off*wordSize),xmm0);
- __ movdqu(Address(rsp,xmm1_off*wordSize),xmm1);
- __ movdqu(Address(rsp,xmm2_off*wordSize),xmm2);
- __ movdqu(Address(rsp,xmm3_off*wordSize),xmm3);
- __ movdqu(Address(rsp,xmm4_off*wordSize),xmm4);
- __ movdqu(Address(rsp,xmm5_off*wordSize),xmm5);
- __ movdqu(Address(rsp,xmm6_off*wordSize),xmm6);
- __ movdqu(Address(rsp,xmm7_off*wordSize),xmm7);
+ if (VM_Version::supports_avx512novl()) {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vextractf32x4h(Address(rsp, off*wordSize), as_XMMRegister(n), 0);
+ off += delta;
+ }
+ } else {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ movdqu(Address(rsp, off*wordSize), as_XMMRegister(n));
+ off += delta;
+ }
+ }
}
if (vect_words > 0) {
assert(vect_words*wordSize == 128, "");
__ subptr(rsp, 128); // Save upper half of YMM registes
- __ vextractf128h(Address(rsp, 0),xmm0);
- __ vextractf128h(Address(rsp, 16),xmm1);
- __ vextractf128h(Address(rsp, 32),xmm2);
- __ vextractf128h(Address(rsp, 48),xmm3);
- __ vextractf128h(Address(rsp, 64),xmm4);
- __ vextractf128h(Address(rsp, 80),xmm5);
- __ vextractf128h(Address(rsp, 96),xmm6);
- __ vextractf128h(Address(rsp,112),xmm7);
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
+ }
if (UseAVX > 2) {
__ subptr(rsp, 256); // Save upper half of ZMM registes
- __ vextractf64x4h(Address(rsp, 0), xmm0);
- __ vextractf64x4h(Address(rsp, 32), xmm1);
- __ vextractf64x4h(Address(rsp, 64), xmm2);
- __ vextractf64x4h(Address(rsp, 96), xmm3);
- __ vextractf64x4h(Address(rsp, 128), xmm4);
- __ vextractf64x4h(Address(rsp, 160), xmm5);
- __ vextractf64x4h(Address(rsp, 192), xmm6);
- __ vextractf64x4h(Address(rsp, 224), xmm7);
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vextractf64x4h(Address(rsp, off++*32), as_XMMRegister(n));
+ }
}
}
@@ -238,58 +230,40 @@
OopMap* map = new OopMap( frame_words, 0 );
#define STACK_OFFSET(x) VMRegImpl::stack2reg((x) + additional_frame_words)
-
- map->set_callee_saved(STACK_OFFSET( rax_off), rax->as_VMReg());
- map->set_callee_saved(STACK_OFFSET( rcx_off), rcx->as_VMReg());
- map->set_callee_saved(STACK_OFFSET( rdx_off), rdx->as_VMReg());
- map->set_callee_saved(STACK_OFFSET( rbx_off), rbx->as_VMReg());
+#define NEXTREG(x) (x)->as_VMReg()->next()
+
+ map->set_callee_saved(STACK_OFFSET(rax_off), rax->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(rcx_off), rcx->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(rdx_off), rdx->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(rbx_off), rbx->as_VMReg());
// rbp, location is known implicitly, no oopMap
- map->set_callee_saved(STACK_OFFSET( rsi_off), rsi->as_VMReg());
- map->set_callee_saved(STACK_OFFSET( rdi_off), rdi->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st0_off), as_FloatRegister(0)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st1_off), as_FloatRegister(1)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st2_off), as_FloatRegister(2)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st3_off), as_FloatRegister(3)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st4_off), as_FloatRegister(4)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st5_off), as_FloatRegister(5)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st6_off), as_FloatRegister(6)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st7_off), as_FloatRegister(7)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm0_off), xmm0->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm1_off), xmm1->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm2_off), xmm2->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm3_off), xmm3->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm4_off), xmm4->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm5_off), xmm5->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm6_off), xmm6->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm7_off), xmm7->as_VMReg());
- // %%% This is really a waste but we'll keep things as they were for now
- if (true) {
-#define NEXTREG(x) (x)->as_VMReg()->next()
- map->set_callee_saved(STACK_OFFSET(st0H_off), NEXTREG(as_FloatRegister(0)));
- map->set_callee_saved(STACK_OFFSET(st1H_off), NEXTREG(as_FloatRegister(1)));
- map->set_callee_saved(STACK_OFFSET(st2H_off), NEXTREG(as_FloatRegister(2)));
- map->set_callee_saved(STACK_OFFSET(st3H_off), NEXTREG(as_FloatRegister(3)));
- map->set_callee_saved(STACK_OFFSET(st4H_off), NEXTREG(as_FloatRegister(4)));
- map->set_callee_saved(STACK_OFFSET(st5H_off), NEXTREG(as_FloatRegister(5)));
- map->set_callee_saved(STACK_OFFSET(st6H_off), NEXTREG(as_FloatRegister(6)));
- map->set_callee_saved(STACK_OFFSET(st7H_off), NEXTREG(as_FloatRegister(7)));
- map->set_callee_saved(STACK_OFFSET(xmm0H_off), NEXTREG(xmm0));
- map->set_callee_saved(STACK_OFFSET(xmm1H_off), NEXTREG(xmm1));
- map->set_callee_saved(STACK_OFFSET(xmm2H_off), NEXTREG(xmm2));
- map->set_callee_saved(STACK_OFFSET(xmm3H_off), NEXTREG(xmm3));
- map->set_callee_saved(STACK_OFFSET(xmm4H_off), NEXTREG(xmm4));
- map->set_callee_saved(STACK_OFFSET(xmm5H_off), NEXTREG(xmm5));
- map->set_callee_saved(STACK_OFFSET(xmm6H_off), NEXTREG(xmm6));
- map->set_callee_saved(STACK_OFFSET(xmm7H_off), NEXTREG(xmm7));
+ map->set_callee_saved(STACK_OFFSET(rsi_off), rsi->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(rdi_off), rdi->as_VMReg());
+ // %%% This is really a waste but we'll keep things as they were for now for the upper component
+ off = st0_off;
+ delta = st1_off - off;
+ for (int n = 0; n < FloatRegisterImpl::number_of_registers; n++) {
+ FloatRegister freg_name = as_FloatRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), freg_name->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(off+1), NEXTREG(freg_name));
+ off += delta;
+ }
+ off = xmm0_off;
+ delta = xmm1_off - off;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(off+1), NEXTREG(xmm_name));
+ off += delta;
+ }
#undef NEXTREG
#undef STACK_OFFSET
- }
return map;
-
}
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
+ int num_xmm_regs = XMMRegisterImpl::number_of_registers;
// Recover XMM & FPU state
int additional_frame_bytes = 0;
#ifdef COMPILER2
@@ -301,52 +275,43 @@
#else
assert(!restore_vectors, "vectors are generated only by C2");
#endif
+ int off = xmm0_off;
+ int delta = xmm1_off - off;
+
if (UseSSE == 1) {
assert(additional_frame_bytes == 0, "");
- __ movflt(xmm0,Address(rsp,xmm0_off*wordSize));
- __ movflt(xmm1,Address(rsp,xmm1_off*wordSize));
- __ movflt(xmm2,Address(rsp,xmm2_off*wordSize));
- __ movflt(xmm3,Address(rsp,xmm3_off*wordSize));
- __ movflt(xmm4,Address(rsp,xmm4_off*wordSize));
- __ movflt(xmm5,Address(rsp,xmm5_off*wordSize));
- __ movflt(xmm6,Address(rsp,xmm6_off*wordSize));
- __ movflt(xmm7,Address(rsp,xmm7_off*wordSize));
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ movflt(as_XMMRegister(n), Address(rsp, off*wordSize));
+ off += delta;
+ }
} else if (UseSSE >= 2) {
-#define STACK_ADDRESS(x) Address(rsp,(x)*wordSize + additional_frame_bytes)
- __ movdqu(xmm0,STACK_ADDRESS(xmm0_off));
- __ movdqu(xmm1,STACK_ADDRESS(xmm1_off));
- __ movdqu(xmm2,STACK_ADDRESS(xmm2_off));
- __ movdqu(xmm3,STACK_ADDRESS(xmm3_off));
- __ movdqu(xmm4,STACK_ADDRESS(xmm4_off));
- __ movdqu(xmm5,STACK_ADDRESS(xmm5_off));
- __ movdqu(xmm6,STACK_ADDRESS(xmm6_off));
- __ movdqu(xmm7,STACK_ADDRESS(xmm7_off));
-#undef STACK_ADDRESS
+ if (VM_Version::supports_avx512novl()) {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vinsertf32x4h(as_XMMRegister(n), Address(rsp, off*wordSize+additional_frame_bytes), 0);
+ off += delta;
+ }
+ } else {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ movdqu(as_XMMRegister(n), Address(rsp, off*wordSize+additional_frame_bytes));
+ off += delta;
+ }
+ }
}
if (restore_vectors) {
+ if (UseAVX > 2) {
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vinsertf64x4h(as_XMMRegister(n), Address(rsp, off++*32));
+ }
+ __ addptr(rsp, additional_frame_bytes*2); // Save upper half of ZMM registes
+ }
// Restore upper half of YMM registes.
assert(additional_frame_bytes == 128, "");
- __ vinsertf128h(xmm0, Address(rsp, 0));
- __ vinsertf128h(xmm1, Address(rsp, 16));
- __ vinsertf128h(xmm2, Address(rsp, 32));
- __ vinsertf128h(xmm3, Address(rsp, 48));
- __ vinsertf128h(xmm4, Address(rsp, 64));
- __ vinsertf128h(xmm5, Address(rsp, 80));
- __ vinsertf128h(xmm6, Address(rsp, 96));
- __ vinsertf128h(xmm7, Address(rsp,112));
- __ addptr(rsp, additional_frame_bytes);
- if (UseAVX > 2) {
- additional_frame_bytes = 256;
- __ vinsertf64x4h(xmm0, Address(rsp, 0));
- __ vinsertf64x4h(xmm1, Address(rsp, 32));
- __ vinsertf64x4h(xmm2, Address(rsp, 64));
- __ vinsertf64x4h(xmm3, Address(rsp, 96));
- __ vinsertf64x4h(xmm4, Address(rsp, 128));
- __ vinsertf64x4h(xmm5, Address(rsp, 160));
- __ vinsertf64x4h(xmm6, Address(rsp, 192));
- __ vinsertf64x4h(xmm7, Address(rsp, 224));
- __ addptr(rsp, additional_frame_bytes);
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
}
+ __ addptr(rsp, additional_frame_bytes); // Save upper half of YMM registes
}
__ pop_FPU_state();
__ addptr(rsp, FPU_regs_live*wordSize); // Pop FPU registers
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -69,7 +69,9 @@
class RegisterSaver {
// Capture info about frame layout. Layout offsets are in jint
// units because compiler frame slots are jints.
+#define HALF_ZMM_BANK_WORDS 128
#define DEF_XMM_OFFS(regnum) xmm ## regnum ## _off = xmm_off + (regnum)*16/BytesPerInt, xmm ## regnum ## H_off
+#define DEF_ZMM_OFFS(regnum) zmm ## regnum ## _off = zmm_off + (regnum-16)*64/BytesPerInt, zmm ## regnum ## H_off
enum layout {
fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area
xmm_off = fpu_state_off + 160/BytesPerInt, // offset in fxsave save area
@@ -89,23 +91,24 @@
DEF_XMM_OFFS(13),
DEF_XMM_OFFS(14),
DEF_XMM_OFFS(15),
- DEF_XMM_OFFS(16),
- DEF_XMM_OFFS(17),
- DEF_XMM_OFFS(18),
- DEF_XMM_OFFS(19),
- DEF_XMM_OFFS(20),
- DEF_XMM_OFFS(21),
- DEF_XMM_OFFS(22),
- DEF_XMM_OFFS(23),
- DEF_XMM_OFFS(24),
- DEF_XMM_OFFS(25),
- DEF_XMM_OFFS(26),
- DEF_XMM_OFFS(27),
- DEF_XMM_OFFS(28),
- DEF_XMM_OFFS(29),
- DEF_XMM_OFFS(30),
- DEF_XMM_OFFS(31),
- fpu_state_end = fpu_state_off + ((FPUStateSizeInWords - 1)*wordSize / BytesPerInt),
+ zmm_off = fpu_state_off + ((FPUStateSizeInWords - (HALF_ZMM_BANK_WORDS + 1))*wordSize / BytesPerInt),
+ DEF_ZMM_OFFS(16),
+ DEF_ZMM_OFFS(17),
+ DEF_ZMM_OFFS(18),
+ DEF_ZMM_OFFS(19),
+ DEF_ZMM_OFFS(20),
+ DEF_ZMM_OFFS(21),
+ DEF_ZMM_OFFS(22),
+ DEF_ZMM_OFFS(23),
+ DEF_ZMM_OFFS(24),
+ DEF_ZMM_OFFS(25),
+ DEF_ZMM_OFFS(26),
+ DEF_ZMM_OFFS(27),
+ DEF_ZMM_OFFS(28),
+ DEF_ZMM_OFFS(29),
+ DEF_ZMM_OFFS(30),
+ DEF_ZMM_OFFS(31),
+ fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt),
fpu_stateH_end,
r15_off, r15H_off,
r14_off, r14H_off,
@@ -155,9 +158,10 @@
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
int vect_words = 0;
- int num_xmm_regs = 16;
- if (UseAVX > 2) {
- num_xmm_regs = 32;
+ int off = 0;
+ int num_xmm_regs = XMMRegisterImpl::number_of_registers;
+ if (UseAVX < 3) {
+ num_xmm_regs = num_xmm_regs/2;
}
#ifdef COMPILER2
if (save_vectors) {
@@ -165,9 +169,7 @@
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
// Save upper half of YMM registers
vect_words = 16 * num_xmm_regs / wordSize;
- additional_frame_words += vect_words;
- if (UseAVX > 2) {
- // Save upper half of ZMM registers as well
+ if (UseAVX < 3) {
additional_frame_words += vect_words;
}
}
@@ -195,77 +197,13 @@
__ enter(); // rsp becomes 16-byte aligned here
__ push_CPU_state(); // Push a multiple of 16 bytes
- if (vect_words > 0) {
+ // push cpu state handles this on EVEX enabled targets
+ if ((vect_words > 0) && (UseAVX < 3)) {
assert(vect_words*wordSize >= 256, "");
- __ subptr(rsp, 256); // Save upper half of YMM registes(0..15)
- __ vextractf128h(Address(rsp, 0), xmm0);
- __ vextractf128h(Address(rsp, 16), xmm1);
- __ vextractf128h(Address(rsp, 32), xmm2);
- __ vextractf128h(Address(rsp, 48), xmm3);
- __ vextractf128h(Address(rsp, 64), xmm4);
- __ vextractf128h(Address(rsp, 80), xmm5);
- __ vextractf128h(Address(rsp, 96), xmm6);
- __ vextractf128h(Address(rsp, 112), xmm7);
- __ vextractf128h(Address(rsp, 128), xmm8);
- __ vextractf128h(Address(rsp, 144), xmm9);
- __ vextractf128h(Address(rsp, 160), xmm10);
- __ vextractf128h(Address(rsp, 176), xmm11);
- __ vextractf128h(Address(rsp, 192), xmm12);
- __ vextractf128h(Address(rsp, 208), xmm13);
- __ vextractf128h(Address(rsp, 224), xmm14);
- __ vextractf128h(Address(rsp, 240), xmm15);
- if (UseAVX > 2) {
- __ subptr(rsp, 256); // Save upper half of YMM registes(16..31)
- __ vextractf128h(Address(rsp, 0), xmm16);
- __ vextractf128h(Address(rsp, 16), xmm17);
- __ vextractf128h(Address(rsp, 32), xmm18);
- __ vextractf128h(Address(rsp, 48), xmm19);
- __ vextractf128h(Address(rsp, 64), xmm20);
- __ vextractf128h(Address(rsp, 80), xmm21);
- __ vextractf128h(Address(rsp, 96), xmm22);
- __ vextractf128h(Address(rsp, 112), xmm23);
- __ vextractf128h(Address(rsp, 128), xmm24);
- __ vextractf128h(Address(rsp, 144), xmm25);
- __ vextractf128h(Address(rsp, 160), xmm26);
- __ vextractf128h(Address(rsp, 176), xmm27);
- __ vextractf128h(Address(rsp, 192), xmm28);
- __ vextractf128h(Address(rsp, 208), xmm29);
- __ vextractf128h(Address(rsp, 224), xmm30);
- __ vextractf128h(Address(rsp, 240), xmm31);
- // Now handle the ZMM registers (0..31)
- __ subptr(rsp, 1024); // Save upper half of ZMM registes
- __ vextractf64x4h(Address(rsp, 0), xmm0);
- __ vextractf64x4h(Address(rsp, 32), xmm1);
- __ vextractf64x4h(Address(rsp, 64), xmm2);
- __ vextractf64x4h(Address(rsp, 96), xmm3);
- __ vextractf64x4h(Address(rsp, 128), xmm4);
- __ vextractf64x4h(Address(rsp, 160), xmm5);
- __ vextractf64x4h(Address(rsp, 192), xmm6);
- __ vextractf64x4h(Address(rsp, 224), xmm7);
- __ vextractf64x4h(Address(rsp, 256), xmm8);
- __ vextractf64x4h(Address(rsp, 288), xmm9);
- __ vextractf64x4h(Address(rsp, 320), xmm10);
- __ vextractf64x4h(Address(rsp, 352), xmm11);
- __ vextractf64x4h(Address(rsp, 384), xmm12);
- __ vextractf64x4h(Address(rsp, 416), xmm13);
- __ vextractf64x4h(Address(rsp, 448), xmm14);
- __ vextractf64x4h(Address(rsp, 480), xmm15);
- __ vextractf64x4h(Address(rsp, 512), xmm16);
- __ vextractf64x4h(Address(rsp, 544), xmm17);
- __ vextractf64x4h(Address(rsp, 576), xmm18);
- __ vextractf64x4h(Address(rsp, 608), xmm19);
- __ vextractf64x4h(Address(rsp, 640), xmm20);
- __ vextractf64x4h(Address(rsp, 672), xmm21);
- __ vextractf64x4h(Address(rsp, 704), xmm22);
- __ vextractf64x4h(Address(rsp, 736), xmm23);
- __ vextractf64x4h(Address(rsp, 768), xmm24);
- __ vextractf64x4h(Address(rsp, 800), xmm25);
- __ vextractf64x4h(Address(rsp, 832), xmm26);
- __ vextractf64x4h(Address(rsp, 864), xmm27);
- __ vextractf64x4h(Address(rsp, 896), xmm28);
- __ vextractf64x4h(Address(rsp, 928), xmm29);
- __ vextractf64x4h(Address(rsp, 960), xmm30);
- __ vextractf64x4h(Address(rsp, 992), xmm31);
+ // Save upper half of YMM registes(0..num_xmm_regs)
+ __ subptr(rsp, num_xmm_regs*16);
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
}
}
if (frame::arg_reg_save_area_bytes != 0) {
@@ -299,39 +237,24 @@
map->set_callee_saved(STACK_OFFSET( r13_off ), r13->as_VMReg());
map->set_callee_saved(STACK_OFFSET( r14_off ), r14->as_VMReg());
map->set_callee_saved(STACK_OFFSET( r15_off ), r15->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm0_off ), xmm0->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm1_off ), xmm1->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm2_off ), xmm2->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm3_off ), xmm3->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm4_off ), xmm4->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm5_off ), xmm5->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm6_off ), xmm6->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm7_off ), xmm7->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm8_off ), xmm8->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm9_off ), xmm9->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm10_off), xmm10->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm11_off), xmm11->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm12_off), xmm12->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm13_off), xmm13->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm14_off), xmm14->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm15_off), xmm15->as_VMReg());
- if (UseAVX > 2) {
- map->set_callee_saved(STACK_OFFSET(xmm16_off), xmm16->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm17_off), xmm17->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm18_off), xmm18->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm19_off), xmm19->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm20_off), xmm20->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm21_off), xmm21->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm22_off), xmm22->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm23_off), xmm23->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm24_off), xmm24->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm25_off), xmm25->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm26_off), xmm26->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm27_off), xmm27->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm28_off), xmm28->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm29_off), xmm29->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm30_off), xmm30->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm31_off), xmm31->as_VMReg());
+ // For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
+ // on EVEX enabled targets, we get it included in the xsave area
+ off = xmm0_off;
+ int delta = xmm1_off - off;
+ for (int n = 0; n < 16; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
+ off += delta;
+ }
+ if(UseAVX > 2) {
+ // Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets
+ off = zmm16_off;
+ delta = zmm17_off - off;
+ for (int n = 16; n < num_xmm_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
+ off += delta;
+ }
}
// %%% These should all be a waste but we'll keep things as they were for now
@@ -351,39 +274,24 @@
map->set_callee_saved(STACK_OFFSET( r13H_off ), r13->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET( r14H_off ), r14->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET( r15H_off ), r15->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm0H_off ), xmm0->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm1H_off ), xmm1->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm2H_off ), xmm2->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm3H_off ), xmm3->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm4H_off ), xmm4->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm5H_off ), xmm5->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm6H_off ), xmm6->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm7H_off ), xmm7->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm8H_off ), xmm8->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm9H_off ), xmm9->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm10H_off), xmm10->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm11H_off), xmm11->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm12H_off), xmm12->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm13H_off), xmm13->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm14H_off), xmm14->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm15H_off), xmm15->as_VMReg()->next());
+ // For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
+ // on EVEX enabled targets, we get it included in the xsave area
+ off = xmm0H_off;
+ delta = xmm1H_off - off;
+ for (int n = 0; n < 16; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()->next());
+ off += delta;
+ }
if (UseAVX > 2) {
- map->set_callee_saved(STACK_OFFSET(xmm16H_off), xmm16->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm17H_off), xmm17->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm18H_off), xmm18->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm19H_off), xmm19->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm20H_off), xmm20->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm21H_off), xmm21->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm22H_off), xmm22->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm23H_off), xmm23->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm24H_off), xmm24->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm25H_off), xmm25->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm26H_off), xmm26->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm27H_off), xmm27->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm28H_off), xmm28->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm29H_off), xmm29->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm30H_off), xmm30->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm31H_off), xmm31->as_VMReg()->next());
+ // Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets
+ off = zmm16H_off;
+ delta = zmm17H_off - off;
+ for (int n = 16; n < num_xmm_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()->next());
+ off += delta;
+ }
}
}
@@ -391,86 +299,25 @@
}
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
+ int num_xmm_regs = XMMRegisterImpl::number_of_registers;
+ if (UseAVX < 3) {
+ num_xmm_regs = num_xmm_regs/2;
+ }
if (frame::arg_reg_save_area_bytes != 0) {
// Pop arg register save area
__ addptr(rsp, frame::arg_reg_save_area_bytes);
}
#ifdef COMPILER2
- if (restore_vectors) {
- // Restore upper half of YMM registes (0..15)
- assert(UseAVX > 0, "512bit vectors are supported only with AVX");
- assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
- __ vinsertf128h(xmm0, Address(rsp, 0));
- __ vinsertf128h(xmm1, Address(rsp, 16));
- __ vinsertf128h(xmm2, Address(rsp, 32));
- __ vinsertf128h(xmm3, Address(rsp, 48));
- __ vinsertf128h(xmm4, Address(rsp, 64));
- __ vinsertf128h(xmm5, Address(rsp, 80));
- __ vinsertf128h(xmm6, Address(rsp, 96));
- __ vinsertf128h(xmm7, Address(rsp,112));
- __ vinsertf128h(xmm8, Address(rsp,128));
- __ vinsertf128h(xmm9, Address(rsp,144));
- __ vinsertf128h(xmm10, Address(rsp,160));
- __ vinsertf128h(xmm11, Address(rsp,176));
- __ vinsertf128h(xmm12, Address(rsp,192));
- __ vinsertf128h(xmm13, Address(rsp,208));
- __ vinsertf128h(xmm14, Address(rsp,224));
- __ vinsertf128h(xmm15, Address(rsp,240));
- __ addptr(rsp, 256);
- if (UseAVX > 2) {
- // Restore upper half of YMM registes (16..31)
- __ vinsertf128h(xmm16, Address(rsp, 0));
- __ vinsertf128h(xmm17, Address(rsp, 16));
- __ vinsertf128h(xmm18, Address(rsp, 32));
- __ vinsertf128h(xmm19, Address(rsp, 48));
- __ vinsertf128h(xmm20, Address(rsp, 64));
- __ vinsertf128h(xmm21, Address(rsp, 80));
- __ vinsertf128h(xmm22, Address(rsp, 96));
- __ vinsertf128h(xmm23, Address(rsp,112));
- __ vinsertf128h(xmm24, Address(rsp,128));
- __ vinsertf128h(xmm25, Address(rsp,144));
- __ vinsertf128h(xmm26, Address(rsp,160));
- __ vinsertf128h(xmm27, Address(rsp,176));
- __ vinsertf128h(xmm28, Address(rsp,192));
- __ vinsertf128h(xmm29, Address(rsp,208));
- __ vinsertf128h(xmm30, Address(rsp,224));
- __ vinsertf128h(xmm31, Address(rsp,240));
- __ addptr(rsp, 256);
- // Restore upper half of ZMM registes.
- __ vinsertf64x4h(xmm0, Address(rsp, 0));
- __ vinsertf64x4h(xmm1, Address(rsp, 32));
- __ vinsertf64x4h(xmm2, Address(rsp, 64));
- __ vinsertf64x4h(xmm3, Address(rsp, 96));
- __ vinsertf64x4h(xmm4, Address(rsp, 128));
- __ vinsertf64x4h(xmm5, Address(rsp, 160));
- __ vinsertf64x4h(xmm6, Address(rsp, 192));
- __ vinsertf64x4h(xmm7, Address(rsp, 224));
- __ vinsertf64x4h(xmm8, Address(rsp, 256));
- __ vinsertf64x4h(xmm9, Address(rsp, 288));
- __ vinsertf64x4h(xmm10, Address(rsp, 320));
- __ vinsertf64x4h(xmm11, Address(rsp, 352));
- __ vinsertf64x4h(xmm12, Address(rsp, 384));
- __ vinsertf64x4h(xmm13, Address(rsp, 416));
- __ vinsertf64x4h(xmm14, Address(rsp, 448));
- __ vinsertf64x4h(xmm15, Address(rsp, 480));
- __ vinsertf64x4h(xmm16, Address(rsp, 512));
- __ vinsertf64x4h(xmm17, Address(rsp, 544));
- __ vinsertf64x4h(xmm18, Address(rsp, 576));
- __ vinsertf64x4h(xmm19, Address(rsp, 608));
- __ vinsertf64x4h(xmm20, Address(rsp, 640));
- __ vinsertf64x4h(xmm21, Address(rsp, 672));
- __ vinsertf64x4h(xmm22, Address(rsp, 704));
- __ vinsertf64x4h(xmm23, Address(rsp, 736));
- __ vinsertf64x4h(xmm24, Address(rsp, 768));
- __ vinsertf64x4h(xmm25, Address(rsp, 800));
- __ vinsertf64x4h(xmm26, Address(rsp, 832));
- __ vinsertf64x4h(xmm27, Address(rsp, 864));
- __ vinsertf64x4h(xmm28, Address(rsp, 896));
- __ vinsertf64x4h(xmm29, Address(rsp, 928));
- __ vinsertf64x4h(xmm30, Address(rsp, 960));
- __ vinsertf64x4h(xmm31, Address(rsp, 992));
- __ addptr(rsp, 1024);
+ // On EVEX enabled targets everything is handled in pop fpu state
+ if ((restore_vectors) && (UseAVX < 3)) {
+ assert(UseAVX > 0, "256/512-bit vectors are supported only with AVX");
+ assert(MaxVectorSize == 64, "up to 512bit vectors are supported now");
+ int off = 0;
+ // Restore upper half of YMM registes (0..num_xmm_regs)
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
}
+ __ addptr(rsp, num_xmm_regs*16);
}
#else
assert(!restore_vectors, "vectors are generated only by C2");
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -722,7 +722,7 @@
__ popa();
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
case BarrierSet::ModRef:
break;
@@ -754,7 +754,7 @@
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
@@ -795,6 +795,12 @@
void xmm_copy_forward(Register from, Register to_from, Register qword_count) {
assert( UseSSE >= 2, "supported cpu only" );
Label L_copy_64_bytes_loop, L_copy_64_bytes, L_copy_8_bytes, L_exit;
+ if (UseAVX > 2) {
+ __ push(rbx);
+ __ movl(rbx, 0xffff);
+ __ kmovdl(k1, rbx);
+ __ pop(rbx);
+ }
// Copy 64-byte chunks
__ jmpb(L_copy_64_bytes);
__ align(OptoLoopAlignment);
@@ -802,8 +808,8 @@
if (UseUnalignedLoadStores) {
if (UseAVX > 2) {
- __ evmovdqu(xmm0, Address(from, 0), Assembler::AVX_512bit);
- __ evmovdqu(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm0, Address(from, 0), Assembler::AVX_512bit);
+ __ evmovdqul(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, 0));
__ vmovdqu(Address(from, to_from, Address::times_1, 0), xmm0);
@@ -2217,6 +2223,15 @@
const XMMRegister xmm_temp4 = xmm5;
__ enter(); // required for proper stackwalking of RuntimeStub frame
+
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
__ movptr(from, from_param);
__ movptr(key, key_param);
@@ -2315,6 +2330,15 @@
const XMMRegister xmm_temp4 = xmm5;
__ enter(); // required for proper stackwalking of RuntimeStub frame
+
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
__ movptr(from, from_param);
__ movptr(key, key_param);
@@ -2441,6 +2465,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
handleSOERegisters(true /*saving*/);
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
// load registers from incoming parameters
const Address from_param(rbp, 8+0);
const Address to_param (rbp, 8+4);
@@ -2602,6 +2634,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
handleSOERegisters(true /*saving*/);
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
// load registers from incoming parameters
const Address from_param(rbp, 8+0);
const Address to_param (rbp, 8+4);
@@ -2782,6 +2822,14 @@
__ enter();
handleSOERegisters(true); // Save registers
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
__ movptr(state, state_param);
__ movptr(subkeyH, subkeyH_param);
__ movptr(data, data_param);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -269,12 +269,16 @@
__ kmovql(k1, rbx);
}
#ifdef _WIN64
+ int last_reg = 15;
if (UseAVX > 2) {
- for (int i = 6; i <= 31; i++) {
- __ movdqu(xmm_save(i), as_XMMRegister(i));
+ last_reg = 31;
+ }
+ if (VM_Version::supports_avx512novl()) {
+ for (int i = xmm_save_first; i <= last_reg; i++) {
+ __ vextractf32x4h(xmm_save(i), as_XMMRegister(i), 0);
}
} else {
- for (int i = 6; i <= 15; i++) {
+ for (int i = xmm_save_first; i <= last_reg; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
}
}
@@ -367,28 +371,34 @@
#ifdef ASSERT
// verify that threads correspond
{
- Label L, S;
+ Label L1, L2, L3;
__ cmpptr(r15_thread, thread);
- __ jcc(Assembler::notEqual, S);
+ __ jcc(Assembler::equal, L1);
+ __ stop("StubRoutines::call_stub: r15_thread is corrupted");
+ __ bind(L1);
__ get_thread(rbx);
+ __ cmpptr(r15_thread, thread);
+ __ jcc(Assembler::equal, L2);
+ __ stop("StubRoutines::call_stub: r15_thread is modified by call");
+ __ bind(L2);
__ cmpptr(r15_thread, rbx);
- __ jcc(Assembler::equal, L);
- __ bind(S);
- __ jcc(Assembler::equal, L);
+ __ jcc(Assembler::equal, L3);
__ stop("StubRoutines::call_stub: threads must correspond");
- __ bind(L);
+ __ bind(L3);
}
#endif
// restore regs belonging to calling function
#ifdef _WIN64
- int xmm_ub = 15;
- if (UseAVX > 2) {
- xmm_ub = 31;
- }
// emit the restores for xmm regs
- for (int i = 6; i <= xmm_ub; i++) {
- __ movdqu(as_XMMRegister(i), xmm_save(i));
+ if (VM_Version::supports_avx512novl()) {
+ for (int i = xmm_save_first; i <= last_reg; i++) {
+ __ vinsertf32x4h(as_XMMRegister(i), xmm_save(i), 0);
+ }
+ } else {
+ for (int i = xmm_save_first; i <= last_reg; i++) {
+ __ movdqu(as_XMMRegister(i), xmm_save(i));
+ }
}
#endif
__ movptr(r15, r15_save);
@@ -450,15 +460,20 @@
#ifdef ASSERT
// verify that threads correspond
{
- Label L, S;
+ Label L1, L2, L3;
__ cmpptr(r15_thread, thread);
- __ jcc(Assembler::notEqual, S);
+ __ jcc(Assembler::equal, L1);
+ __ stop("StubRoutines::catch_exception: r15_thread is corrupted");
+ __ bind(L1);
__ get_thread(rbx);
+ __ cmpptr(r15_thread, thread);
+ __ jcc(Assembler::equal, L2);
+ __ stop("StubRoutines::catch_exception: r15_thread is modified by call");
+ __ bind(L2);
__ cmpptr(r15_thread, rbx);
- __ jcc(Assembler::equal, L);
- __ bind(S);
+ __ jcc(Assembler::equal, L3);
__ stop("StubRoutines::catch_exception: threads must correspond");
- __ bind(L);
+ __ bind(L3);
}
#endif
@@ -1244,7 +1259,7 @@
__ popa();
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
case BarrierSet::ModRef:
break;
@@ -1284,7 +1299,7 @@
__ popa();
}
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
@@ -1333,11 +1348,15 @@
__ align(OptoLoopAlignment);
if (UseUnalignedLoadStores) {
Label L_end;
+ if (UseAVX > 2) {
+ __ movl(to, 0xffff);
+ __ kmovql(k1, to);
+ }
// Copy 64-bytes per iteration
__ BIND(L_loop);
if (UseAVX > 2) {
- __ evmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56), Assembler::AVX_512bit);
- __ evmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm0, Address(end_from, qword_count, Address::times_8, -56), Assembler::AVX_512bit);
+ __ evmovdqul(Address(end_to, qword_count, Address::times_8, -56), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56));
__ vmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0);
@@ -1413,11 +1432,15 @@
__ align(OptoLoopAlignment);
if (UseUnalignedLoadStores) {
Label L_end;
+ if (UseAVX > 2) {
+ __ movl(to, 0xffff);
+ __ kmovql(k1, to);
+ }
// Copy 64-bytes per iteration
__ BIND(L_loop);
if (UseAVX > 2) {
- __ evmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32), Assembler::AVX_512bit);
- __ evmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm0, Address(from, qword_count, Address::times_8, 32), Assembler::AVX_512bit);
+ __ evmovdqul(Address(dest, qword_count, Address::times_8, 32), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32));
__ vmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0);
@@ -3097,6 +3120,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
// keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
@@ -3191,6 +3222,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
// keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
@@ -3303,6 +3342,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
#ifdef _WIN64
// on win64, fill len_reg from stack position
__ movl(len_reg, len_mem);
@@ -3499,6 +3546,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
#ifdef _WIN64
// on win64, fill len_reg from stack position
__ movl(len_reg, len_mem);
@@ -3737,6 +3792,14 @@
__ enter();
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
#ifdef _WIN64
// save the xmm registers which must be preserved 6-10
__ subptr(rsp, -rsp_after_call_off * wordSize);
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -31,7 +31,7 @@
enum platform_dependent_constants {
code_size1 = 9000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
+ code_size2 = 30000 // simply increase if too small (assembler will crash if too small)
};
class x86 {
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -33,7 +33,7 @@
enum platform_dependent_constants {
code_size1 = 19000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 24000 // simply increase if too small (assembler will crash if too small)
+ code_size2 = 32000 // simply increase if too small (assembler will crash if too small)
};
class x86 {
--- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -200,7 +200,7 @@
}
break;
#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
{
if (val == noreg) {
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -367,16 +367,12 @@
__ movl(rcx, VM_Version::ymm_test_value());
__ movdl(xmm0, rcx);
__ movl(rcx, 0xffff);
+ __ kmovwl(k1, rcx);
+ __ evpbroadcastd(xmm0, xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm7, xmm0, Assembler::AVX_512bit);
#ifdef _LP64
- __ kmovql(k1, rcx);
-#else
- __ kmovdl(k1, rcx);
-#endif
- __ evpbroadcastd(xmm0, xmm0, Assembler::AVX_512bit);
- __ evmovdqu(xmm7, xmm0, Assembler::AVX_512bit);
-#ifdef _LP64
- __ evmovdqu(xmm8, xmm0, Assembler::AVX_512bit);
- __ evmovdqu(xmm31, xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm8, xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm31, xmm0, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
__ jmp(save_restore_except);
@@ -427,11 +423,11 @@
UseAVX = 3;
UseSSE = 2;
__ lea(rsi, Address(rbp, in_bytes(VM_Version::zmm_save_offset())));
- __ evmovdqu(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
- __ evmovdqu(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
+ __ evmovdqul(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
#ifdef _LP64
- __ evmovdqu(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
- __ evmovdqu(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
+ __ evmovdqul(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
+ __ evmovdqul(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
UseAVX = saved_useavx;
@@ -714,6 +710,11 @@
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
}
+ if (UseAdler32Intrinsics) {
+ warning("Adler32Intrinsics not available on this CPU.");
+ FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+ }
+
// Adjust RTM (Restricted Transactional Memory) flags
if (!supports_rtm() && UseRTMLocking) {
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -227,14 +227,15 @@
union XemXcr0Eax {
uint32_t value;
struct {
- uint32_t x87 : 1,
- sse : 1,
- ymm : 1,
- : 2,
- opmask : 1,
- zmm512 : 1,
- zmm32 : 1,
- : 24;
+ uint32_t x87 : 1,
+ sse : 1,
+ ymm : 1,
+ bndregs : 1,
+ bndcsr : 1,
+ opmask : 1,
+ zmm512 : 1,
+ zmm32 : 1,
+ : 24;
} bits;
};
@@ -703,6 +704,7 @@
static bool supports_avx512bw() { return (_cpuFeatures & CPU_AVX512BW) != 0; }
static bool supports_avx512vl() { return (_cpuFeatures & CPU_AVX512VL) != 0; }
static bool supports_avx512vlbw() { return (supports_avx512bw() && supports_avx512vl()); }
+ static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); }
// Intel features
static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
@@ -817,6 +819,12 @@
intx count = PrefetchFieldsAhead;
return count >= 0 ? count : 1;
}
+ static uint32_t get_xsave_header_lower_segment() {
+ return _cpuid_info.xem_xcr0_eax.value;
+ }
+ static uint32_t get_xsave_header_upper_segment() {
+ return _cpuid_info.xem_xcr0_edx;
+ }
};
#endif // CPU_X86_VM_VM_VERSION_X86_HPP
--- a/hotspot/src/cpu/x86/vm/x86.ad Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/x86.ad Mon Sep 14 07:03:04 2015 +0000
@@ -1661,46 +1661,55 @@
if (!has_match_rule(opcode))
return false;
+ bool ret_value = true;
switch (opcode) {
case Op_PopCountI:
case Op_PopCountL:
if (!UsePopCountInstruction)
- return false;
- break;
+ ret_value = false;
+ break;
case Op_MulVI:
if ((UseSSE < 4) && (UseAVX < 1)) // only with SSE4_1 or AVX
- return false;
- break;
+ ret_value = false;
+ break;
case Op_MulVL:
case Op_MulReductionVL:
if (VM_Version::supports_avx512dq() == false)
- return false;
+ ret_value = false;
+ break;
case Op_AddReductionVL:
if (UseAVX < 3) // only EVEX : vector connectivity becomes an issue here
- return false;
+ ret_value = false;
+ break;
case Op_AddReductionVI:
if (UseSSE < 3) // requires at least SSE3
- return false;
+ ret_value = false;
+ break;
case Op_MulReductionVI:
if (UseSSE < 4) // requires at least SSE4
- return false;
+ ret_value = false;
+ break;
case Op_AddReductionVF:
case Op_AddReductionVD:
case Op_MulReductionVF:
case Op_MulReductionVD:
if (UseSSE < 1) // requires at least SSE
- return false;
- break;
+ ret_value = false;
+ break;
+ case Op_SqrtVD:
+ if (UseAVX < 1) // enabled for AVX only
+ ret_value = false;
+ break;
case Op_CompareAndSwapL:
#ifdef _LP64
case Op_CompareAndSwapP:
#endif
if (!VM_Version::supports_cx8())
- return false;
- break;
+ ret_value = false;
+ break;
}
- return true; // Per default match rules are supported.
+ return ret_value; // Per default match rules are supported.
}
// Max vector size in bytes. 0 if not supported.
@@ -1721,14 +1730,24 @@
case T_DOUBLE:
case T_LONG:
if (size < 16) return 0;
+ break;
case T_FLOAT:
case T_INT:
if (size < 8) return 0;
+ break;
case T_BOOLEAN:
+ if (size < 4) return 0;
+ break;
+ case T_CHAR:
+ if (size < 4) return 0;
+ break;
case T_BYTE:
- case T_CHAR:
+ if (size < 4) return 0;
+ if ((size > 32) && !VM_Version::supports_avx512bw()) return 0;
+ break;
case T_SHORT:
if (size < 4) return 0;
+ if ((size > 16) && !VM_Version::supports_avx512bw()) return 0;
break;
default:
ShouldNotReachHere();
@@ -1800,7 +1819,7 @@
__ vmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]));
break;
case Op_VecZ:
- __ evmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 2);
+ __ evmovdqul(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 2);
break;
default:
ShouldNotReachHere();
@@ -1855,7 +1874,7 @@
__ vmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset));
break;
case Op_VecZ:
- __ evmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset), 2);
+ __ evmovdqul(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset), 2);
break;
default:
ShouldNotReachHere();
@@ -1875,7 +1894,7 @@
__ vmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]));
break;
case Op_VecZ:
- __ evmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 2);
+ __ evmovdqul(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 2);
break;
default:
ShouldNotReachHere();
@@ -1929,9 +1948,40 @@
}
#endif
}
- int offset_size = (stack_offset == 0) ? 0 : ((stack_offset < 0x80) ? 1 : (UseAVX > 2) ? 6 : 4);
+ bool is_single_byte = false;
+ int vec_len = 0;
+ if ((UseAVX > 2) && (stack_offset != 0)) {
+ switch (ireg) {
+ case Op_VecS:
+ case Op_VecD:
+ case Op_VecX:
+ break;
+ case Op_VecY:
+ vec_len = 1;
+ break;
+ case Op_VecZ:
+ vec_len = 2;
+ break;
+ }
+ is_single_byte = Assembler::query_compressed_disp_byte(stack_offset, true, vec_len, Assembler::EVEX_FVM, Assembler::EVEX_32bit, 0);
+ }
+ int offset_size = 0;
+ int size = 5;
+ if (UseAVX > 2 ) {
+ if ((VM_Version::supports_avx512vl() == false) && (vec_len == 2)) {
+ offset_size = (stack_offset == 0) ? 0 : ((is_single_byte) ? 1 : 4);
+ size += 2; // Need an additional two bytes for EVEX encoding
+ } else if ((VM_Version::supports_avx512vl() == false) && (vec_len < 2)) {
+ offset_size = (stack_offset == 0) ? 0 : ((stack_offset <= 127) ? 1 : 4);
+ } else {
+ offset_size = (stack_offset == 0) ? 0 : ((is_single_byte) ? 1 : 4);
+ size += 2; // Need an additional two bytes for EVEX encodding
+ }
+ } else {
+ offset_size = (stack_offset == 0) ? 0 : ((stack_offset <= 127) ? 1 : 4);
+ }
// VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix.
- return 5+offset_size;
+ return size+offset_size;
}
static inline jfloat replicate4_imm(int con, int width) {
@@ -2675,11 +2725,10 @@
predicate(UseAVX > 0);
match(Set dst (NegF src));
ins_cost(150);
- format %{ "vxorps $dst, $src, [0x80000000]\t# neg float by sign flipping" %}
- ins_encode %{
- int vector_len = 0;
- __ vxorps($dst$$XMMRegister, $src$$XMMRegister,
- ExternalAddress(float_signflip()), vector_len);
+ format %{ "vnegatess $dst, $src, [0x80000000]\t# neg float by sign flipping" %}
+ ins_encode %{
+ __ vnegatess($dst$$XMMRegister, $src$$XMMRegister,
+ ExternalAddress(float_signflip()));
%}
ins_pipe(pipe_slow);
%}
@@ -2700,12 +2749,11 @@
predicate(UseAVX > 0);
match(Set dst (NegD src));
ins_cost(150);
- format %{ "vxorpd $dst, $src, [0x8000000000000000]\t"
+ format %{ "vnegatess $dst, $src, [0x8000000000000000]\t"
"# neg double by sign flipping" %}
ins_encode %{
- int vector_len = 0;
- __ vxorpd($dst$$XMMRegister, $src$$XMMRegister,
- ExternalAddress(double_signflip()), vector_len);
+ __ vnegatesd($dst$$XMMRegister, $src$$XMMRegister,
+ ExternalAddress(double_signflip()));
%}
ins_pipe(pipe_slow);
%}
@@ -2838,7 +2886,7 @@
format %{ "vmovdqu $dst k0,$mem\t! load vector (64 bytes)" %}
ins_encode %{
int vector_len = 2;
- __ evmovdqu($dst$$XMMRegister, $mem$$Address, vector_len);
+ __ evmovdqul($dst$$XMMRegister, $mem$$Address, vector_len);
%}
ins_pipe( pipe_slow );
%}
@@ -2895,7 +2943,7 @@
format %{ "vmovdqu $mem k0,$src\t! store vector (64 bytes)" %}
ins_encode %{
int vector_len = 2;
- __ evmovdqu($mem$$Address, $src$$XMMRegister, vector_len);
+ __ evmovdqul($mem$$Address, $src$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
%}
@@ -3315,6 +3363,37 @@
ins_pipe( pipe_slow );
%}
+instruct Repl2F_zero(vecD dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 2 && UseAVX < 3);
+ match(Set dst (ReplicateF zero));
+ format %{ "xorps $dst,$dst\t! replicate2F zero" %}
+ ins_encode %{
+ __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl4F_zero(vecX dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 4 && UseAVX < 3);
+ match(Set dst (ReplicateF zero));
+ format %{ "xorps $dst,$dst\t! replicate4F zero" %}
+ ins_encode %{
+ __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl8F_zero(vecY dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 8 && UseAVX < 3);
+ match(Set dst (ReplicateF zero));
+ format %{ "vxorps $dst,$dst,$dst\t! replicate8F zero" %}
+ ins_encode %{
+ int vector_len = 1;
+ __ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
instruct Repl2D_mem(vecX dst, memory mem) %{
predicate(n->as_Vector()->length() == 2 && UseAVX > 0 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateD (LoadD mem)));
@@ -3349,6 +3428,28 @@
ins_pipe( pipe_slow );
%}
+// Replicate double (8 byte) scalar zero to be vector
+instruct Repl2D_zero(vecX dst, immD0 zero) %{
+ predicate(n->as_Vector()->length() == 2 && UseAVX < 3);
+ match(Set dst (ReplicateD zero));
+ format %{ "xorpd $dst,$dst\t! replicate2D zero" %}
+ ins_encode %{
+ __ xorpd($dst$$XMMRegister, $dst$$XMMRegister);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl4D_zero(vecY dst, immD0 zero) %{
+ predicate(n->as_Vector()->length() == 4 && UseAVX < 3);
+ match(Set dst (ReplicateD zero));
+ format %{ "vxorpd $dst,$dst,$dst,vect256\t! replicate4D zero" %}
+ ins_encode %{
+ int vector_len = 1;
+ __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
// ====================GENERIC REPLICATE==========================================
// Replicate byte scalar to be vector
@@ -3680,38 +3781,6 @@
ins_pipe( pipe_slow );
%}
-// Replicate float (4 byte) scalar zero to be vector
-instruct Repl2F_zero(vecD dst, immF0 zero) %{
- predicate(n->as_Vector()->length() == 2);
- match(Set dst (ReplicateF zero));
- format %{ "xorps $dst,$dst\t! replicate2F zero" %}
- ins_encode %{
- __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct Repl4F_zero(vecX dst, immF0 zero) %{
- predicate(n->as_Vector()->length() == 4);
- match(Set dst (ReplicateF zero));
- format %{ "xorps $dst,$dst\t! replicate4F zero" %}
- ins_encode %{
- __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct Repl8F_zero(vecY dst, immF0 zero) %{
- predicate(n->as_Vector()->length() == 8);
- match(Set dst (ReplicateF zero));
- format %{ "vxorps $dst,$dst,$dst\t! replicate8F zero" %}
- ins_encode %{
- int vector_len = 1;
- __ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
// Replicate double (8 bytes) scalar to be vector
instruct Repl2D(vecX dst, regD src) %{
predicate(n->as_Vector()->length() == 2);
@@ -3723,28 +3792,6 @@
ins_pipe( pipe_slow );
%}
-// Replicate double (8 byte) scalar zero to be vector
-instruct Repl2D_zero(vecX dst, immD0 zero) %{
- predicate(n->as_Vector()->length() == 2);
- match(Set dst (ReplicateD zero));
- format %{ "xorpd $dst,$dst\t! replicate2D zero" %}
- ins_encode %{
- __ xorpd($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct Repl4D_zero(vecY dst, immD0 zero) %{
- predicate(n->as_Vector()->length() == 4);
- match(Set dst (ReplicateD zero));
- format %{ "vxorpd $dst,$dst,$dst,vect256\t! replicate4D zero" %}
- ins_encode %{
- int vector_len = 1;
- __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
// ====================EVEX REPLICATE=============================================
instruct Repl4B_mem_evex(vecS dst, memory mem) %{
@@ -3814,7 +3861,7 @@
%}
instruct Repl64B_evex(vecZ dst, rRegI src) %{
- predicate(n->as_Vector()->length() == 64 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB src));
format %{ "vpbroadcastb $dst,$src\t! upper replicate64B" %}
ins_encode %{
@@ -3825,7 +3872,7 @@
%}
instruct Repl64B_mem_evex(vecZ dst, memory mem) %{
- predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512vlbw());
+ predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB (LoadB mem)));
format %{ "vpbroadcastb $dst,$mem\t! replicate64B" %}
ins_encode %{
@@ -3862,7 +3909,7 @@
%}
instruct Repl64B_imm_evex(vecZ dst, immI con) %{
- predicate(n->as_Vector()->length() == 64 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB con));
format %{ "movq $dst,[$constantaddress]\n\t"
"vpbroadcastb $dst,$dst\t! upper replicate64B" %}
@@ -3953,7 +4000,7 @@
%}
instruct Repl32S_evex(vecZ dst, rRegI src) %{
- predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS src));
format %{ "vpbroadcastw $dst,$src\t! replicate32S" %}
ins_encode %{
@@ -3964,7 +4011,7 @@
%}
instruct Repl32S_mem_evex(vecZ dst, memory mem) %{
- predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS (LoadS mem)));
format %{ "vpbroadcastw $dst,$mem\t! replicate32S" %}
ins_encode %{
@@ -4001,7 +4048,7 @@
%}
instruct Repl32S_imm_evex(vecZ dst, immI con) %{
- predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS con));
format %{ "movq $dst,[$constantaddress]\n\t"
"vpbroadcastw $dst,$dst\t! replicate32S" %}
@@ -4318,13 +4365,50 @@
ins_pipe( pipe_slow );
%}
+instruct Repl2F_zero_evex(vecD dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 2 && UseAVX > 2);
+ match(Set dst (ReplicateF zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate2F zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl4F_zero_evex(vecX dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 4 && UseAVX > 2);
+ match(Set dst (ReplicateF zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate4F zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl8F_zero_evex(vecY dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 8 && UseAVX > 2);
+ match(Set dst (ReplicateF zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate8F zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
instruct Repl16F_zero_evex(vecZ dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 16 && UseAVX > 2);
match(Set dst (ReplicateF zero));
- format %{ "vxorps $dst k0,$dst,$dst\t! replicate16F zero" %}
- ins_encode %{
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate16F zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
int vector_len = 2;
- __ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
@@ -4373,13 +4457,38 @@
ins_pipe( pipe_slow );
%}
+instruct Repl2D_zero_evex(vecX dst, immD0 zero) %{
+ predicate(n->as_Vector()->length() == 2 && UseAVX > 2);
+ match(Set dst (ReplicateD zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate2D zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl4D_zero_evex(vecY dst, immD0 zero) %{
+ predicate(n->as_Vector()->length() == 4 && UseAVX > 2);
+ match(Set dst (ReplicateD zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate4D zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
instruct Repl8D_zero_evex(vecZ dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 8 && UseAVX > 2);
match(Set dst (ReplicateD zero));
- format %{ "vxorpd $dst k0,$dst,$dst,vect512\t! replicate8D zero" %}
- ins_encode %{
+ format %{ "vpxor $dst k0,$dst,$dst,vect512\t! replicate8D zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
int vector_len = 2;
- __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
@@ -7474,6 +7583,75 @@
ins_pipe( pipe_slow );
%}
+// --------------------------------- Sqrt --------------------------------------
+
+// Floating point vector sqrt - double precision only
+instruct vsqrt2D_reg(vecX dst, vecX src) %{
+ predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
+ match(Set dst (SqrtVD src));
+ format %{ "vsqrtpd $dst,$src\t! sqrt packed2D" %}
+ ins_encode %{
+ int vector_len = 0;
+ __ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt2D_mem(vecX dst, memory mem) %{
+ predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
+ match(Set dst (SqrtVD (LoadVector mem)));
+ format %{ "vsqrtpd $dst,$mem\t! sqrt packed2D" %}
+ ins_encode %{
+ int vector_len = 0;
+ __ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt4D_reg(vecY dst, vecY src) %{
+ predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
+ match(Set dst (SqrtVD src));
+ format %{ "vsqrtpd $dst,$src\t! sqrt packed4D" %}
+ ins_encode %{
+ int vector_len = 1;
+ __ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt4D_mem(vecY dst, memory mem) %{
+ predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
+ match(Set dst (SqrtVD (LoadVector mem)));
+ format %{ "vsqrtpd $dst,$mem\t! sqrt packed4D" %}
+ ins_encode %{
+ int vector_len = 1;
+ __ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt8D_reg(vecZ dst, vecZ src) %{
+ predicate(UseAVX > 2 && n->as_Vector()->length() == 8);
+ match(Set dst (SqrtVD src));
+ format %{ "vsqrtpd $dst,$src\t! sqrt packed8D" %}
+ ins_encode %{
+ int vector_len = 2;
+ __ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt8D_mem(vecZ dst, memory mem) %{
+ predicate(UseAVX > 2 && n->as_Vector()->length() == 8);
+ match(Set dst (SqrtVD (LoadVector mem)));
+ format %{ "vsqrtpd $dst,$mem\t! sqrt packed8D" %}
+ ins_encode %{
+ int vector_len = 2;
+ __ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
// ------------------------------ LeftShift -----------------------------------
// Shorts/Chars vector left shift
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Mon Sep 14 07:03:04 2015 +0000
@@ -1004,10 +1004,10 @@
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
case Op_VecZ:
- __ evmovdqu(Address(rsp, -64), xmm0, 2);
- __ evmovdqu(xmm0, Address(rsp, src_offset), 2);
- __ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
- __ evmovdqu(xmm0, Address(rsp, -64), 2);
+ __ evmovdqul(Address(rsp, -64), xmm0, 2);
+ __ evmovdqul(xmm0, Address(rsp, src_offset), 2);
+ __ evmovdqul(Address(rsp, dst_offset), xmm0, 2);
+ __ evmovdqul(xmm0, Address(rsp, -64), 2);
break;
default:
ShouldNotReachHere();
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Mon Sep 14 07:03:04 2015 +0000
@@ -1075,10 +1075,10 @@
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
case Op_VecZ:
- __ evmovdqu(Address(rsp, -64), xmm0, 2);
- __ evmovdqu(xmm0, Address(rsp, src_offset), 2);
- __ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
- __ evmovdqu(xmm0, Address(rsp, -64), 2);
+ __ evmovdqul(Address(rsp, -64), xmm0, 2);
+ __ evmovdqul(xmm0, Address(rsp, src_offset), 2);
+ __ evmovdqul(Address(rsp, dst_offset), xmm0, 2);
+ __ evmovdqul(xmm0, Address(rsp, -64), 2);
break;
default:
ShouldNotReachHere();
--- a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -53,6 +53,10 @@
return cpuinfo_field_contains("cpu", "Niagara");
}
+static bool detect_M_family() {
+ return cpuinfo_field_contains("cpu", "SPARC-M");
+}
+
static bool detect_blkinit() {
return cpuinfo_field_contains("cpucaps", "blkinit");
}
@@ -66,6 +70,11 @@
features = niagara1_m | T_family_m;
}
+ if (detect_M_family()) {
+ NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Detected Linux on M family");)
+ features = sun4v_m | generic_v9_m | M_family_m | T_family_m;
+ }
+
if (detect_blkinit()) {
features |= blk_init_instructions_m;
}
--- a/hotspot/src/share/vm/adlc/Doc/Syntax.doc Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/adlc/Doc/Syntax.doc Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
the architecture of a processor, and is the input to the ADL Compiler. The
ADL Compiler compiles an ADL file into code which is incorporated into the
Optimizing Just In Time Compiler (OJIT) to generate efficient and correct code
-for the target architecture. The ADL describes three bassic different types
+for the target architecture. The ADL describes three basic different types
of architectural features. It describes the instruction set (and associated
operands) of the target architecture. It describes the register set of the
target architecture along with relevant information for the register allocator.
--- a/hotspot/src/share/vm/adlc/formssel.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -4143,6 +4143,7 @@
"SubVB","SubVS","SubVI","SubVL","SubVF","SubVD",
"MulVS","MulVI","MulVL","MulVF","MulVD",
"DivVF","DivVD",
+ "SqrtVD",
"AndV" ,"XorV" ,"OrV",
"AddReductionVI", "AddReductionVL",
"AddReductionVF", "AddReductionVD",
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -32,7 +32,6 @@
#include "c1/c1_Runtime1.hpp"
#include "c1/c1_ValueType.hpp"
#include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -4212,7 +4212,7 @@
if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
return;
}
- CompileTask::print_inlining(callee, scope()->level(), bci(), msg);
+ CompileTask::print_inlining_tty(callee, scope()->level(), bci(), msg);
if (success && CIPrintMethodCodes) {
callee->print_codes();
}
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1425,7 +1425,7 @@
G1SATBCardTableModRef_pre_barrier(addr_opr, pre_val, do_load, patch, info);
break;
#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
// No pre barriers
break;
@@ -1445,7 +1445,7 @@
G1SATBCardTableModRef_post_barrier(addr, new_val);
break;
#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
CardTableModRef_post_barrier(addr, new_val);
break;
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1447,7 +1447,6 @@
if (methodData() == NULL)
return;
- bool printit = _method->should_print_assembly();
if (methodData()->has_escape_info()) {
TRACE_BCEA(2, tty->print_cr("[EA] Reading previous results for %s.%s",
method->holder()->name()->as_utf8(),
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -28,8 +28,8 @@
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderExt.hpp"
-#include "classfile/imageFile.hpp"
#include "classfile/javaClasses.hpp"
+#include "classfile/jimage.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
@@ -58,6 +58,7 @@
#include "runtime/os.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
+#include "runtime/vm_version.hpp"
#include "services/management.hpp"
#include "services/threadService.hpp"
#include "utilities/events.hpp"
@@ -68,7 +69,7 @@
#include "classfile/sharedPathsMiscInfo.hpp"
#endif
-// Entry points in zip.dll for loading zip/jar file entries and image file entries
+// Entry points in zip.dll for loading zip/jar file entries
typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
typedef void (JNICALL *ZipClose_t)(jzfile *zip);
@@ -89,6 +90,15 @@
static ZipInflateFully_t ZipInflateFully = NULL;
static Crc32_t Crc32 = NULL;
+// Entry points for jimage.dll for loading jimage file entries
+
+static JImageOpen_t JImageOpen = NULL;
+static JImageClose_t JImageClose = NULL;
+static JImagePackageToModule_t JImagePackageToModule = NULL;
+static JImageFindResource_t JImageFindResource = NULL;
+static JImageGetResource_t JImageGetResource = NULL;
+static JImageResourceIterator_t JImageResourceIterator = NULL;
+
// Globals
PerfCounter* ClassLoader::_perf_accumulated_time = NULL;
@@ -141,6 +151,15 @@
return (strncmp(str, str_to_find, str_to_find_len) == 0);
}
+static const char* get_jimage_version_string() {
+ static char version_string[10] = "";
+ if (version_string[0] == '\0') {
+ jio_snprintf(version_string, sizeof(version_string), "%d.%d",
+ Abstract_VM_Version::vm_minor_version(), Abstract_VM_Version::vm_micro_version());
+ }
+ return (const char*)version_string;
+}
+
bool string_ends_with(const char* str, const char* str_to_find) {
size_t str_len = strlen(str);
size_t str_to_find_len = strlen(str_to_find);
@@ -272,98 +291,114 @@
}
}
-ClassPathImageEntry::ClassPathImageEntry(ImageFileReader* image) :
+ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) :
ClassPathEntry(),
- _image(image),
- _module_data(NULL) {
- guarantee(image != NULL, "image file is null");
-
- char module_data_name[JVM_MAXPATHLEN];
- ImageModuleData::module_data_name(module_data_name, _image->name());
- _module_data = new ImageModuleData(_image, module_data_name);
+ _jimage(jimage) {
+ guarantee(jimage != NULL, "jimage file is null");
+ guarantee(name != NULL, "jimage file name is null");
+ size_t len = strlen(name) + 1;
+ _name = NEW_C_HEAP_ARRAY(const char, len, mtClass);
+ strncpy((char *)_name, name, len);
}
ClassPathImageEntry::~ClassPathImageEntry() {
- if (_module_data != NULL) {
- delete _module_data;
- _module_data = NULL;
+ if (_name != NULL) {
+ FREE_C_HEAP_ARRAY(const char, _name);
+ _name = NULL;
}
-
- if (_image != NULL) {
- ImageFileReader::close(_image);
- _image = NULL;
+ if (_jimage != NULL) {
+ (*JImageClose)(_jimage);
+ _jimage = NULL;
}
}
-const char* ClassPathImageEntry::name() {
- return _image ? _image->name() : "";
+void ClassPathImageEntry::name_to_package(const char* name, char* buffer, int length) {
+ const char *pslash = strrchr(name, '/');
+ if (pslash == NULL) {
+ buffer[0] = '\0';
+ return;
+ }
+ int len = pslash - name;
+#if INCLUDE_CDS
+ if (len <= 0 && DumpSharedSpaces) {
+ buffer[0] = '\0';
+ return;
+ }
+#endif
+ assert(len > 0, "Bad length for package name");
+ if (len >= length) {
+ buffer[0] = '\0';
+ return;
+ }
+ // drop name after last slash (including slash)
+ // Ex., "java/lang/String.class" => "java/lang"
+ strncpy(buffer, name, len);
+ // ensure string termination (strncpy does not guarantee)
+ buffer[len] = '\0';
}
+// For a class in a named module, look it up in the jimage file using this syntax:
+// /<module-name>/<package-name>/<base-class>
+//
+// Assumptions:
+// 1. There are no unnamed modules in the jimage file.
+// 2. A package is in at most one module in the jimage file.
+//
ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
- ImageLocation location;
- bool found = _image->find_location(name, location);
-
- if (!found) {
- const char *pslash = strrchr(name, '/');
- int len = pslash - name;
+ jlong size;
+ JImageLocationRef location = (*JImageFindResource)(_jimage, "", get_jimage_version_string(), name, &size);
- // NOTE: IMAGE_MAX_PATH is used here since this path is internal to the jimage
- // (effectively unlimited.) There are several JCK tests that use paths over
- // 1024 characters long, the limit on Windows systems.
- if (pslash && 0 < len && len < IMAGE_MAX_PATH) {
-
- char path[IMAGE_MAX_PATH];
- strncpy(path, name, len);
- path[len] = '\0';
- const char* moduleName = _module_data->package_to_module(path);
-
- if (moduleName != NULL && (len + strlen(moduleName) + 2) < IMAGE_MAX_PATH) {
- jio_snprintf(path, IMAGE_MAX_PATH - 1, "/%s/%s", moduleName, name);
- location.clear_data();
- found = _image->find_location(path, location);
- }
+ if (location == 0) {
+ char package[JIMAGE_MAX_PATH];
+ name_to_package(name, package, JIMAGE_MAX_PATH);
+ if (package[0] != '\0') {
+ const char* module = (*JImagePackageToModule)(_jimage, package);
+ if (module == NULL) {
+ module = "java.base";
+ }
+ location = (*JImageFindResource)(_jimage, module, get_jimage_version_string(), name, &size);
}
}
- if (found) {
- u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
+ if (location != 0) {
if (UsePerfData) {
ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
}
- u1* data = NEW_RESOURCE_ARRAY(u1, size);
- _image->get_resource(location, data);
- return new ClassFileStream(data, (int)size, _image->name()); // Resource allocated
+ char* data = NEW_RESOURCE_ARRAY(char, size);
+ (*JImageGetResource)(_jimage, location, data, size);
+ return new ClassFileStream((u1*)data, (int)size, _name); // Resource allocated
}
return NULL;
}
#ifndef PRODUCT
+bool ctw_visitor(JImageFile* jimage,
+ const char* module_name, const char* version, const char* package,
+ const char* name, const char* extension, void* arg) {
+ if (strcmp(extension, "class") == 0) {
+ Thread* THREAD = Thread::current();
+ char path[JIMAGE_MAX_PATH];
+ jio_snprintf(path, JIMAGE_MAX_PATH - 1, "%s/%s.class", package, name);
+ ClassLoader::compile_the_world_in(path, *(Handle*)arg, THREAD);
+ return !HAS_PENDING_EXCEPTION;
+ }
+ return true;
+}
+
void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
tty->print_cr("CompileTheWorld : Compiling all classes in %s", name());
tty->cr();
- const ImageStrings strings = _image->get_strings();
- // Retrieve each path component string.
- u4 length = _image->table_length();
- for (u4 i = 0; i < length; i++) {
- u1* location_data = _image->get_location_data(i);
-
- if (location_data != NULL) {
- ImageLocation location(location_data);
- char path[IMAGE_MAX_PATH];
- _image->location_path(location, path, IMAGE_MAX_PATH);
- ClassLoader::compile_the_world_in(path, loader, CHECK);
+ (*JImageResourceIterator)(_jimage, (JImageResourceVisitor_t)ctw_visitor, (void *)&loader);
+ if (HAS_PENDING_EXCEPTION) {
+ if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
+ CLEAR_PENDING_EXCEPTION;
+ tty->print_cr("\nCompileTheWorld : Ran out of memory\n");
+ tty->print_cr("Increase class metadata storage if a limit was set");
+ } else {
+ tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n");
}
}
- if (HAS_PENDING_EXCEPTION) {
- if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
- CLEAR_PENDING_EXCEPTION;
- tty->print_cr("\nCompileTheWorld : Ran out of memory\n");
- tty->print_cr("Increase class metadata storage if a limit was set");
- } else {
- tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n");
- }
- }
}
bool ClassPathImageEntry::is_jrt() {
@@ -490,7 +525,7 @@
JavaThread* thread = JavaThread::current();
ClassPathEntry* new_entry = NULL;
if ((st->st_mode & S_IFREG) == S_IFREG) {
- // Regular file, should be a zip or image file
+ // Regular file, should be a zip or jimage file
// Canonicalized filename
char canonical_path[JVM_MAXPATHLEN];
if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
@@ -501,9 +536,10 @@
return NULL;
}
}
- ImageFileReader* image = ImageFileReader::open(canonical_path);
- if (image != NULL) {
- new_entry = new ClassPathImageEntry(image);
+ jint error;
+ JImageFile* jimage =(*JImageOpen)(canonical_path, &error);
+ if (jimage != NULL) {
+ new_entry = new ClassPathImageEntry(jimage, canonical_path);
} else {
char* error_msg = NULL;
jzfile* zip;
@@ -682,6 +718,35 @@
// This lookup only works on 1.3. Do not check for non-null here
}
+void ClassLoader::load_jimage_library() {
+ // First make sure native library is loaded
+ os::native_java_library();
+ // Load jimage library
+ char path[JVM_MAXPATHLEN];
+ char ebuf[1024];
+ void* handle = NULL;
+ if (os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "jimage")) {
+ handle = os::dll_load(path, ebuf, sizeof ebuf);
+ }
+ if (handle == NULL) {
+ vm_exit_during_initialization("Unable to load jimage library", path);
+ }
+
+ // Lookup jimage entry points
+ JImageOpen = CAST_TO_FN_PTR(JImageOpen_t, os::dll_lookup(handle, "JIMAGE_Open"));
+ guarantee(JImageOpen != NULL, "function JIMAGE_Open not found");
+ JImageClose = CAST_TO_FN_PTR(JImageClose_t, os::dll_lookup(handle, "JIMAGE_Close"));
+ guarantee(JImageClose != NULL, "function JIMAGE_Close not found");
+ JImagePackageToModule = CAST_TO_FN_PTR(JImagePackageToModule_t, os::dll_lookup(handle, "JIMAGE_PackageToModule"));
+ guarantee(JImagePackageToModule != NULL, "function JIMAGE_PackageToModule not found");
+ JImageFindResource = CAST_TO_FN_PTR(JImageFindResource_t, os::dll_lookup(handle, "JIMAGE_FindResource"));
+ guarantee(JImageFindResource != NULL, "function JIMAGE_FindResource not found");
+ JImageGetResource = CAST_TO_FN_PTR(JImageGetResource_t, os::dll_lookup(handle, "JIMAGE_GetResource"));
+ guarantee(JImageGetResource != NULL, "function JIMAGE_GetResource not found");
+ JImageResourceIterator = CAST_TO_FN_PTR(JImageResourceIterator_t, os::dll_lookup(handle, "JIMAGE_ResourceIterator"));
+ guarantee(JImageResourceIterator != NULL, "function JIMAGE_ResourceIterator not found");
+}
+
jboolean ClassLoader::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) {
return (*ZipInflateFully)(in, inSize, out, outSize, pmsg);
}
@@ -1086,6 +1151,8 @@
// lookup zip library entry points
load_zip_library();
+ // lookup jimage library entry points
+ load_jimage_library();
#if INCLUDE_CDS
// initialize search path
if (DumpSharedSpaces) {
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -37,8 +37,7 @@
// Class path entry (directory or zip file)
-class ImageFileReader;
-class ImageModuleData;
+class JImageFile;
class ClassPathEntry: public CHeapObj<mtClass> {
private:
@@ -52,7 +51,7 @@
}
virtual bool is_jar_file() = 0;
virtual const char* name() = 0;
- virtual ImageFileReader* image() = 0;
+ virtual JImageFile* jimage() = 0;
// Constructor
ClassPathEntry();
// Attempt to locate file_name through this class path entry.
@@ -70,7 +69,7 @@
public:
bool is_jar_file() { return false; }
const char* name() { return _dir; }
- ImageFileReader* image() { return NULL; }
+ JImageFile* jimage() { return NULL; }
ClassPathDirEntry(const char* dir);
ClassFileStream* open_stream(const char* name, TRAPS);
// Debugging
@@ -100,7 +99,7 @@
public:
bool is_jar_file() { return true; }
const char* name() { return _zip_name; }
- ImageFileReader* image() { return NULL; }
+ JImageFile* jimage() { return NULL; }
ClassPathZipEntry(jzfile* zip, const char* zip_name);
~ClassPathZipEntry();
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
@@ -115,16 +114,16 @@
// For java image files
class ClassPathImageEntry: public ClassPathEntry {
private:
- ImageFileReader* _image;
- ImageModuleData* _module_data;
+ JImageFile* _jimage;
+ const char* _name;
public:
bool is_jar_file() { return false; }
- bool is_open() { return _image != NULL; }
- const char* name();
- ImageFileReader* image() { return _image; }
- ImageModuleData* module_data() { return _module_data; }
- ClassPathImageEntry(ImageFileReader* image);
+ bool is_open() { return _jimage != NULL; }
+ const char* name() { return _name == NULL ? "" : _name; }
+ JImageFile* jimage() { return _jimage; }
+ ClassPathImageEntry(JImageFile* jimage, const char* name);
~ClassPathImageEntry();
+ static void name_to_package(const char* name, char* buffer, int length);
ClassFileStream* open_stream(const char* name, TRAPS);
// Debugging
@@ -206,6 +205,7 @@
static void setup_search_path(const char *class_path);
static void load_zip_library();
+ static void load_jimage_library();
static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
bool throw_exception, TRAPS);
--- a/hotspot/src/share/vm/classfile/imageDecompressor.cpp Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "runtime/thread.inline.hpp"
-#include "classfile/imageDecompressor.hpp"
-#include "runtime/thread.hpp"
-#include "utilities/bytes.hpp"
-
-/*
- * Allocate in C Heap not in resource area, otherwise JVM crashes.
- * This array life time is the VM life time. Array is never freed and
- * is not expected to contain more than few references.
- */
-GrowableArray<ImageDecompressor*>* ImageDecompressor::_decompressors =
- new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageDecompressor*>(2, true);
-
-static Symbol* createSymbol(const char* str) {
- Thread* THREAD = Thread::current();
- Symbol* sym = SymbolTable::lookup(str, (int) strlen(str), THREAD);
- if (HAS_PENDING_EXCEPTION) {
- warning("can't create symbol\n");
- CLEAR_PENDING_EXCEPTION;
- return NULL;
- }
- return sym;
-}
-
-/*
- * Initialize the array of decompressors.
- */
-bool image_decompressor_init() {
- Symbol* zipSymbol = createSymbol("zip");
- if (zipSymbol == NULL) {
- return false;
- }
- ImageDecompressor::add_decompressor(new ZipDecompressor(zipSymbol));
-
- return true;
-}
-
-/*
- * Decompression entry point. Called from ImageFileReader::get_resource.
- */
-void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed,
- u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap) {
- bool has_header = false;
- u1* decompressed_resource = compressed;
- u1* compressed_resource = compressed;
-
- // Resource could have been transformed by a stack of decompressors.
- // Iterate and decompress resources until there is no more header.
- do {
- ResourceHeader _header;
- memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
- has_header = _header._magic == ResourceHeader::resource_header_magic;
- if (has_header) {
- // decompressed_resource array contains the result of decompression
- // when a resource content is terminal, it means that it is an actual resource,
- // not an intermediate not fully uncompressed content. In this case
- // the resource is allocated as an mtClass, otherwise as an mtOther
- decompressed_resource = is_C_heap && _header._is_terminal ?
- NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtClass) :
- NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtOther);
- // Retrieve the decompressor name
- const char* decompressor_name = strings->get(_header._decompressor_name_offset);
- if (decompressor_name == NULL) warning("image decompressor not found\n");
- guarantee(decompressor_name, "image decompressor not found");
- // Retrieve the decompressor instance
- ImageDecompressor* decompressor = get_decompressor(decompressor_name);
- if (decompressor == NULL) {
- warning("image decompressor %s not found\n", decompressor_name);
- }
- guarantee(decompressor, "image decompressor not found");
- u1* compressed_resource_base = compressed_resource;
- compressed_resource += ResourceHeader::resource_header_length;
- // Ask the decompressor to decompress the compressed content
- decompressor->decompress_resource(compressed_resource, decompressed_resource,
- &_header, strings);
- if (compressed_resource_base != compressed) {
- FREE_C_HEAP_ARRAY(char, compressed_resource_base);
- }
- compressed_resource = decompressed_resource;
- }
- } while (has_header);
- memcpy(uncompressed, decompressed_resource, uncompressed_size);
-}
-
-// Zip decompressor
-
-void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed,
- ResourceHeader* header, const ImageStrings* strings) {
- char* msg = NULL;
- jboolean res = ClassLoader::decompress(data, header->_size, uncompressed,
- header->_uncompressed_size, &msg);
- if (!res) warning("decompression failed due to %s\n", msg);
- guarantee(res, "decompression failed");
-}
-
-// END Zip Decompressor
--- a/hotspot/src/share/vm/classfile/imageDecompressor.hpp Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 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 SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
-#define SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
-
-#include "runtime/thread.inline.hpp"
-#include "classfile/classLoader.hpp"
-#include "classfile/imageFile.hpp"
-#include "classfile/symbolTable.hpp"
-#include "oops/symbol.hpp"
-#include "utilities/growableArray.hpp"
-
-/*
- * Compressed resources located in image have an header.
- * This header contains:
- * - _magic: A magic u4, required to retrieved the header in the compressed content
- * - _size: The size of the compressed resource.
- * - _uncompressed_size: The uncompressed size of the compressed resource.
- * - _decompressor_name_offset: The ImageDecompressor instance name StringsTable offset.
- * - _decompressor_config_offset: StringsTable offset of configuration that could be needed by
- * the decompressor in order to decompress.
- * - _is_terminal: 1: the compressed content is terminal. Uncompressing it would
- * create the actual resource. 0: the compressed content is not terminal. Uncompressing it
- * will result in a compressed content to be decompressed (This occurs when a stack of compressors
- * have been used to compress the resource.
- */
-struct ResourceHeader {
- /* Length of header, needed to retrieve content offset */
- static const u1 resource_header_length = 21;
- /* magic bytes that identifies a compressed resource header*/
- static const u4 resource_header_magic = 0xCAFEFAFA;
- u4 _magic; // Resource header
- u4 _size; // Resource size
- u4 _uncompressed_size; // Expected uncompressed size
- u4 _decompressor_name_offset; // Strings table decompressor offset
- u4 _decompressor_config_offset; // Strings table config offset
- u1 _is_terminal; // Last decompressor 1, otherwise 0.
-};
-
-/*
- * Resources located in jimage file can be compressed. Compression occurs at
- * jimage file creation time. When compressed a resource is added an header that
- * contains the name of the compressor that compressed it.
- * Various compression strategies can be applied to compress a resource.
- * The same resource can even be compressed multiple time by a stack of compressors.
- * At runtime, a resource is decompressed in a loop until there is no more header
- * meaning that the resource is equivalent to the not compressed resource.
- * In each iteration, the name of the compressor located in the current header
- * is used to retrieve the associated instance of ImageDecompressor.
- * For example “zip” is the name of the compressor that compresses resources
- * using the zip algorithm. The ZipDecompressor class name is also “zip”.
- * ImageDecompressor instances are retrieved from a static array in which
- * they are registered.
- */
-class ImageDecompressor: public CHeapObj<mtClass> {
-
-private:
- const Symbol* _name;
-
- /*
- * Array of concrete decompressors. This array is used to retrieve the decompressor
- * that can handle resource decompression.
- */
- static GrowableArray<ImageDecompressor*>* _decompressors;
-
- /*
- * Identifier of a decompressor. This name is the identification key to retrieve
- * decompressor from a resource header.
- */
- inline const Symbol* get_name() const { return _name; }
-
-protected:
- ImageDecompressor(const Symbol* name) : _name(name) {
- }
- virtual void decompress_resource(u1* data, u1* uncompressed,
- ResourceHeader* header, const ImageStrings* strings) = 0;
-
-public:
- inline static void add_decompressor(ImageDecompressor* decompressor) {
- _decompressors->append(decompressor);
- }
- inline static ImageDecompressor* get_decompressor(const char * decompressor_name) {
- Thread* THREAD = Thread::current();
- TempNewSymbol sym = SymbolTable::new_symbol(decompressor_name,
- (int) strlen(decompressor_name), CHECK_NULL);
- if (HAS_PENDING_EXCEPTION) {
- warning("can't create symbol\n");
- CLEAR_PENDING_EXCEPTION;
- return NULL;
- }
- for (int i = 0; i < _decompressors->length(); i++) {
- ImageDecompressor* decompressor = _decompressors->at(i);
- if (decompressor->get_name()->fast_compare(sym) == 0) {
- return decompressor;
- }
- }
- guarantee(false, "No decompressor found.");
- return NULL;
- }
- static void decompress_resource(u1* compressed, u1* uncompressed,
- u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap);
-};
-
-/**
- * Zip decompressor.
- */
-class ZipDecompressor : public ImageDecompressor {
-public:
- ZipDecompressor(const Symbol* sym) : ImageDecompressor(sym) { }
- void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header,
- const ImageStrings* strings);
-};
-
-#endif // SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
--- a/hotspot/src/share/vm/classfile/imageFile.cpp Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,546 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "classfile/imageDecompressor.hpp"
-#include "classfile/imageFile.hpp"
-#include "memory/resourceArea.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "runtime/os.inline.hpp"
-#include "utilities/endian.hpp"
-#include "utilities/growableArray.hpp"
-
-// Image files are an alternate file format for storing classes and resources. The
-// goal is to supply file access which is faster and smaller than the jar format.
-//
-// (More detailed nodes in the header.)
-//
-
-// Compute the Perfect Hashing hash code for the supplied UTF-8 string.
-s4 ImageStrings::hash_code(const char* string, s4 seed) {
- // Access bytes as unsigned.
- u1* bytes = (u1*)string;
- // Compute hash code.
- for (u1 byte = *bytes++; byte; byte = *bytes++) {
- seed = (seed * HASH_MULTIPLIER) ^ byte;
- }
- // Ensure the result is not signed.
- return seed & 0x7FFFFFFF;
-}
-
-// Match up a string in a perfect hash table. Result still needs validation
-// for precise match (false positive.)
-s4 ImageStrings::find(Endian* endian, const char* name, s4* redirect, u4 length) {
- // If the table is empty, then short cut.
- if (redirect == NULL || length == 0) {
- return NOT_FOUND;
- }
- // Compute the basic perfect hash for name.
- s4 hash_code = ImageStrings::hash_code(name);
- // Modulo table size.
- s4 index = hash_code % length;
- // Get redirect entry.
- // value == 0 then not found
- // value < 0 then -1 - value is true index
- // value > 0 then value is seed for recomputing hash.
- s4 value = endian->get(redirect[index]);
- // if recompute is required.
- if (value > 0) {
- // Entry collision value, need to recompute hash.
- hash_code = ImageStrings::hash_code(name, value);
- // Modulo table size.
- return hash_code % length;
- } else if (value < 0) {
- // Compute direct index.
- return -1 - value;
- }
- // No entry found.
- return NOT_FOUND;
-}
-
-// Test to see if UTF-8 string begins with the start UTF-8 string. If so,
-// return non-NULL address of remaining portion of string. Otherwise, return
-// NULL. Used to test sections of a path without copying from image string
-// table.
-const char* ImageStrings::starts_with(const char* string, const char* start) {
- char ch1, ch2;
- // Match up the strings the best we can.
- while ((ch1 = *string) && (ch2 = *start)) {
- if (ch1 != ch2) {
- // Mismatch, return NULL.
- return NULL;
- }
- // Next characters.
- string++, start++;
- }
- // Return remainder of string.
- return string;
-}
-
-// Inflates the attribute stream into individual values stored in the long
-// array _attributes. This allows an attribute value to be quickly accessed by
-// direct indexing. Unspecified values default to zero (from constructor.)
-void ImageLocation::set_data(u1* data) {
- // Deflate the attribute stream into an array of attributes.
- u1 byte;
- // Repeat until end header is found.
- while ((byte = *data)) {
- // Extract kind from header byte.
- u1 kind = attribute_kind(byte);
- guarantee(kind < ATTRIBUTE_COUNT, "invalid image location attribute");
- // Extract length of data (in bytes).
- u1 n = attribute_length(byte);
- // Read value (most significant first.)
- _attributes[kind] = attribute_value(data + 1, n);
- // Position to next attribute by skipping attribute header and data bytes.
- data += n + 1;
- }
-}
-
-// Zero all attribute values.
-void ImageLocation::clear_data() {
- // Set defaults to zero.
- memset(_attributes, 0, sizeof(_attributes));
-}
-
-// ImageModuleData constructor maps out sub-tables for faster access.
-ImageModuleData::ImageModuleData(const ImageFileReader* image_file,
- const char* module_data_name) :
- _image_file(image_file),
- _endian(image_file->endian()),
- _strings(image_file->get_strings()) {
- // Retrieve the resource containing the module data for the image file.
- ImageLocation location;
- bool found = image_file->find_location(module_data_name, location);
- guarantee(found, "missing module data");
- u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
- _data = (u1*)NEW_C_HEAP_ARRAY(char, data_size, mtClass);
- _image_file->get_resource(location, _data);
- // Map out the header.
- _header = (Header*)_data;
- // Get the package to module entry count.
- u4 ptm_count = _header->ptm_count(_endian);
- // Get the module to package entry count.
- u4 mtp_count = _header->mtp_count(_endian);
- // Compute the offset of the package to module perfect hash redirect.
- u4 ptm_redirect_offset = sizeof(Header);
- // Compute the offset of the package to module data.
- u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4);
- // Compute the offset of the module to package perfect hash redirect.
- u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData);
- // Compute the offset of the module to package data.
- u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4);
- // Compute the offset of the module to package tables.
- u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData);
- // Compute the address of the package to module perfect hash redirect.
- _ptm_redirect = (s4*)(_data + ptm_redirect_offset);
- // Compute the address of the package to module data.
- _ptm_data = (PTMData*)(_data + ptm_data_offset);
- // Compute the address of the module to package perfect hash redirect.
- _mtp_redirect = (s4*)(_data + mtp_redirect_offset);
- // Compute the address of the module to package data.
- _mtp_data = (MTPData*)(_data + mtp_data_offset);
- // Compute the address of the module to package tables.
- _mtp_packages = (s4*)(_data + mtp_packages_offset);
-}
-
-// Release module data resource.
-ImageModuleData::~ImageModuleData() {
- if (_data != NULL) {
- FREE_C_HEAP_ARRAY(u1, _data);
- }
-}
-
-// Return the name of the module data resource. Ex. "./lib/modules/file.jimage"
-// yields "file.jdata"
-void ImageModuleData::module_data_name(char* buffer, const char* image_file_name) {
- // Locate the last slash in the file name path.
- const char* slash = strrchr(image_file_name, os::file_separator()[0]);
- // Trim the path to name and extension.
- const char* name = slash != NULL ? slash + 1 : (char *)image_file_name;
- // Locate the extension period.
- const char* dot = strrchr(name, '.');
- guarantee(dot, "missing extension on jimage name");
- // Trim to only base name.
- int length = dot - name;
- strncpy(buffer, name, length);
- buffer[length] = '\0';
- // Append extension.
- strcat(buffer, ".jdata");
-}
-
-// Return the module in which a package resides. Returns NULL if not found.
-const char* ImageModuleData::package_to_module(const char* package_name) {
- // Search the package to module table.
- s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect,
- _header->ptm_count(_endian));
- // If entry is found.
- if (index != ImageStrings::NOT_FOUND) {
- // Retrieve the package to module entry.
- PTMData* data = _ptm_data + index;
- // Verify that it is the correct data.
- if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) {
- return NULL;
- }
- // Return the module name.
- return get_string(data->module_name_offset(_endian));
- }
- return NULL;
-}
-
-// Returns all the package names in a module. Returns NULL if module not found.
-GrowableArray<const char*>* ImageModuleData::module_to_packages(const char* module_name) {
- // Search the module to package table.
- s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect,
- _header->mtp_count(_endian));
- // If entry is found.
- if (index != ImageStrings::NOT_FOUND) {
- // Retrieve the module to package entry.
- MTPData* data = _mtp_data + index;
- // Verify that it is the correct data.
- if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) {
- return NULL;
- }
- // Construct an array of all the package entries.
- GrowableArray<const char*>* packages = new GrowableArray<const char*>();
- s4 package_offset = data->package_offset(_endian);
- for (u4 i = 0; i < data->package_count(_endian); i++) {
- u4 package_name_offset = mtp_package(package_offset + i);
- const char* package_name = get_string(package_name_offset);
- packages->append(package_name);
- }
- return packages;
- }
- return NULL;
-}
-
-// Table to manage multiple opens of an image file.
-GrowableArray<ImageFileReader*>* ImageFileReader::_reader_table =
- new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageFileReader*>(2, true);
-
-// Open an image file, reuse structure if file already open.
-ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) {
- // Lock out _reader_table.
- MutexLocker ml(ImageFileReaderTable_lock);
- ImageFileReader* reader;
- // Search for an exist image file.
- for (int i = 0; i < _reader_table->length(); i++) {
- // Retrieve table entry.
- reader = _reader_table->at(i);
- // If name matches, then reuse (bump up use count.)
- if (strcmp(reader->name(), name) == 0) {
- reader->inc_use();
- return reader;
- }
- }
- // Need a new image reader.
- reader = new ImageFileReader(name, big_endian);
- bool opened = reader->open();
- // If failed to open.
- if (!opened) {
- delete reader;
- return NULL;
- }
- // Bump use count and add to table.
- reader->inc_use();
- _reader_table->append(reader);
- return reader;
-}
-
-// Close an image file if the file is not in use elsewhere.
-void ImageFileReader::close(ImageFileReader *reader) {
- // Lock out _reader_table.
- MutexLocker ml(ImageFileReaderTable_lock);
- // If last use then remove from table and then close.
- if (reader->dec_use()) {
- _reader_table->remove(reader);
- delete reader;
- }
-}
-
-// Return an id for the specifed ImageFileReader.
-u8 ImageFileReader::readerToID(ImageFileReader *reader) {
- // ID is just the cloaked reader address.
- return (u8)reader;
-}
-
-// Validate the image id.
-bool ImageFileReader::idCheck(u8 id) {
- // Make sure the ID is a managed (_reader_table) reader.
- MutexLocker ml(ImageFileReaderTable_lock);
- return _reader_table->contains((ImageFileReader*)id);
-}
-
-// Return an id for the specifed ImageFileReader.
-ImageFileReader* ImageFileReader::idToReader(u8 id) {
-#ifdef PRODUCT
- // Fast convert.
- return (ImageFileReader*)id;
-#else
- // Do a slow check before fast convert.
- return idCheck(id) ? (ImageFileReader*)id : NULL;
-#endif
-}
-
-// Constructor intializes to a closed state.
-ImageFileReader::ImageFileReader(const char* name, bool big_endian) {
- // Copy the image file name.
- _name = NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtClass);
- strcpy(_name, name);
- // Initialize for a closed file.
- _fd = -1;
- _endian = Endian::get_handler(big_endian);
- _index_data = NULL;
-}
-
-// Close image and free up data structures.
-ImageFileReader::~ImageFileReader() {
- // Ensure file is closed.
- close();
- // Free up name.
- if (_name != NULL) {
- FREE_C_HEAP_ARRAY(char, _name);
- _name = NULL;
- }
-}
-
-// Open image file for read access.
-bool ImageFileReader::open() {
- // If file exists open for reading.
- struct stat st;
- if (os::stat(_name, &st) != 0 ||
- (st.st_mode & S_IFREG) != S_IFREG ||
- (_fd = os::open(_name, 0, O_RDONLY)) == -1) {
- return false;
- }
- // Retrieve the file size.
- _file_size = (u8)st.st_size;
- // Read image file header and verify it has a valid header.
- size_t header_size = sizeof(ImageHeader);
- if (_file_size < header_size ||
- !read_at((u1*)&_header, header_size, 0) ||
- _header.magic(_endian) != IMAGE_MAGIC ||
- _header.major_version(_endian) != MAJOR_VERSION ||
- _header.minor_version(_endian) != MINOR_VERSION) {
- close();
- return false;
- }
- // Size of image index.
- _index_size = index_size();
- // Make sure file is large enough to contain the index.
- if (_file_size < _index_size) {
- return false;
- }
- // Determine how much of the image is memory mapped.
- off_t map_size = (off_t)(MemoryMapImage ? _file_size : _index_size);
- // Memory map image (minimally the index.)
- _index_data = (u1*)os::map_memory(_fd, _name, 0, NULL, map_size, true, false);
- guarantee(_index_data, "image file not memory mapped");
- // Retrieve length of index perfect hash table.
- u4 length = table_length();
- // Compute offset of the perfect hash table redirect table.
- u4 redirect_table_offset = (u4)header_size;
- // Compute offset of index attribute offsets.
- u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4);
- // Compute offset of index location attribute data.
- u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4);
- // Compute offset of index string table.
- u4 string_bytes_offset = location_bytes_offset + locations_size();
- // Compute address of the perfect hash table redirect table.
- _redirect_table = (s4*)(_index_data + redirect_table_offset);
- // Compute address of index attribute offsets.
- _offsets_table = (u4*)(_index_data + offsets_table_offset);
- // Compute address of index location attribute data.
- _location_bytes = _index_data + location_bytes_offset;
- // Compute address of index string table.
- _string_bytes = _index_data + string_bytes_offset;
- // Successful open.
- return true;
-}
-
-// Close image file.
-void ImageFileReader::close() {
- // Dealllocate the index.
- if (_index_data != NULL) {
- os::unmap_memory((char*)_index_data, _index_size);
- _index_data = NULL;
- }
- // Close file.
- if (_fd != -1) {
- os::close(_fd);
- _fd = -1;
- }
-}
-
-// Read directly from the file.
-bool ImageFileReader::read_at(u1* data, u8 size, u8 offset) const {
- return os::read_at(_fd, data, size, offset) == size;
-}
-
-// Find the location attributes associated with the path. Returns true if
-// the location is found, false otherwise.
-bool ImageFileReader::find_location(const char* path, ImageLocation& location) const {
- // Locate the entry in the index perfect hash table.
- s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
- // If is found.
- if (index != ImageStrings::NOT_FOUND) {
- // Get address of first byte of location attribute stream.
- u1* data = get_location_data(index);
- // Expand location attributes.
- location.set_data(data);
- // Make sure result is not a false positive.
- return verify_location(location, path);
- }
- return false;
-}
-
-// Assemble the location path from the string fragments indicated in the location attributes.
-void ImageFileReader::location_path(ImageLocation& location, char* path, size_t max) const {
- // Manage the image string table.
- ImageStrings strings(_string_bytes, _header.strings_size(_endian));
- // Position to first character of the path buffer.
- char* next = path;
- // Temp for string length.
- size_t length;
- // Get module string.
- const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
- // If module string is not empty string.
- if (*module != '\0') {
- // Get length of module name.
- length = strlen(module);
- // Make sure there is no buffer overflow.
- guarantee(next - path + length + 2 < max, "buffer overflow");
- // Append '/module/'.
- *next++ = '/';
- strcpy(next, module); next += length;
- *next++ = '/';
- }
- // Get parent (package) string.
- const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
- // If parent string is not empty string.
- if (*parent != '\0') {
- // Get length of module string.
- length = strlen(parent);
- // Make sure there is no buffer overflow.
- guarantee(next - path + length + 1 < max, "buffer overflow");
- // Append 'patent/' .
- strcpy(next, parent); next += length;
- *next++ = '/';
- }
- // Get base name string.
- const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
- // Get length of base name.
- length = strlen(base);
- // Make sure there is no buffer overflow.
- guarantee(next - path + length < max, "buffer overflow");
- // Append base name.
- strcpy(next, base); next += length;
- // Get extension string.
- const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
- // If extension string is not empty string.
- if (*extension != '\0') {
- // Get length of extension string.
- length = strlen(extension);
- // Make sure there is no buffer overflow.
- guarantee(next - path + length + 1 < max, "buffer overflow");
- // Append '.extension' .
- *next++ = '.';
- strcpy(next, extension); next += length;
- }
- // Make sure there is no buffer overflow.
- guarantee((size_t)(next - path) < max, "buffer overflow");
- // Terminate string.
- *next = '\0';
-}
-
-// Verify that a found location matches the supplied path (without copying.)
-bool ImageFileReader::verify_location(ImageLocation& location, const char* path) const {
- // Manage the image string table.
- ImageStrings strings(_string_bytes, _header.strings_size(_endian));
- // Position to first character of the path string.
- const char* next = path;
- // Get module name string.
- const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
- // If module string is not empty.
- if (*module != '\0') {
- // Compare '/module/' .
- if (*next++ != '/') return false;
- if (!(next = ImageStrings::starts_with(next, module))) return false;
- if (*next++ != '/') return false;
- }
- // Get parent (package) string
- const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
- // If parent string is not empty string.
- if (*parent != '\0') {
- // Compare 'parent/' .
- if (!(next = ImageStrings::starts_with(next, parent))) return false;
- if (*next++ != '/') return false;
- }
- // Get base name string.
- const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
- // Compare with basne name.
- if (!(next = ImageStrings::starts_with(next, base))) return false;
- // Get extension string.
- const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
- // If extension is not empty.
- if (*extension != '\0') {
- // Compare '.extension' .
- if (*next++ != '.') return false;
- if (!(next = ImageStrings::starts_with(next, extension))) return false;
- }
- // True only if complete match and no more characters.
- return *next == '\0';
-}
-
-// Return the resource data for the supplied location.
-void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_data) const {
- // Retrieve the byte offset and size of the resource.
- u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
- u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
- u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED);
- if (compressed_size != 0) {
- ResourceMark rm;
- u1* compressed_data;
- // If not memory mapped read in bytes.
- if (!MemoryMapImage) {
- // Allocate buffer for compression.
- compressed_data = NEW_RESOURCE_ARRAY(u1, compressed_size);
- // Read bytes from offset beyond the image index.
- bool is_read = read_at(compressed_data, compressed_size, _index_size + offset);
- guarantee(is_read, "error reading from image or short read");
- } else {
- compressed_data = get_data_address() + offset;
- }
- // Get image string table.
- const ImageStrings strings = get_strings();
- // Decompress resource.
- ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, uncompressed_size,
- &strings, false);
- } else {
- // Read bytes from offset beyond the image index.
- bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset);
- guarantee(is_read, "error reading from image or short read");
- }
-}
--- a/hotspot/src/share/vm/classfile/imageFile.hpp Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,602 +0,0 @@
-/*
- * Copyright (c) 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 SHARE_VM_CLASSFILE_IMAGEFILE_HPP
-#define SHARE_VM_CLASSFILE_IMAGEFILE_HPP
-
-#include "classfile/classLoader.hpp"
-#include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-#include "utilities/endian.hpp"
-#include "utilities/globalDefinitions.hpp"
-#include "utilities/growableArray.hpp"
-
-// Image files are an alternate file format for storing classes and resources. The
-// goal is to supply file access which is faster and smaller than the jar format.
-// It should be noted that unlike jars, information stored in an image is in native
-// endian format. This allows the image to be mapped into memory without endian
-// translation. This also means that images are platform dependent.
-//
-// Image files are structured as three sections;
-//
-// +-----------+
-// | Header |
-// +-----------+
-// | |
-// | Index |
-// | |
-// +-----------+
-// | |
-// | |
-// | Resources |
-// | |
-// | |
-// +-----------+
-//
-// The header contains information related to identification and description of
-// contents.
-//
-// +-------------------------+
-// | Magic (0xCAFEDADA) |
-// +------------+------------+
-// | Major Vers | Minor Vers |
-// +------------+------------+
-// | Flags |
-// +-------------------------+
-// | Resource Count |
-// +-------------------------+
-// | Table Length |
-// +-------------------------+
-// | Attributes Size |
-// +-------------------------+
-// | Strings Size |
-// +-------------------------+
-//
-// Magic - means of identifying validity of the file. This avoids requiring a
-// special file extension.
-// Major vers, minor vers - differences in version numbers indicate structural
-// changes in the image.
-// Flags - various image wide flags (future).
-// Resource count - number of resources in the file.
-// Table length - the length of lookup tables used in the index.
-// Attributes size - number of bytes in the region used to store location attribute
-// streams.
-// Strings size - the size of the region used to store strings used by the
-// index and meta data.
-//
-// The index contains information related to resource lookup. The algorithm
-// used for lookup is "A Practical Minimal Perfect Hashing Method"
-// (http://homepages.dcc.ufmg.br/~nivio/papers/wea05.pdf). Given a path string
-// in the form /<module>/<package>/<base>.<extension> return the resource location
-// information;
-//
-// redirectIndex = hash(path, DEFAULT_SEED) % table_length;
-// redirect = redirectTable[redirectIndex];
-// if (redirect == 0) return not found;
-// locationIndex = redirect < 0 ? -1 - redirect : hash(path, redirect) % table_length;
-// location = locationTable[locationIndex];
-// if (!verify(location, path)) return not found;
-// return location;
-//
-// Note: The hash function takes an initial seed value. A different seed value
-// usually returns a different result for strings that would otherwise collide with
-// other seeds. The verify function guarantees the found resource location is
-// indeed the resource we are looking for.
-//
-// The following is the format of the index;
-//
-// +-------------------+
-// | Redirect Table |
-// +-------------------+
-// | Attribute Offsets |
-// +-------------------+
-// | Attribute Data |
-// +-------------------+
-// | Strings |
-// +-------------------+
-//
-// Redirect Table - Array of 32-bit signed values representing actions that
-// should take place for hashed strings that map to that
-// value. Negative values indicate no hash collision and can be
-// quickly converted to indices into attribute offsets. Positive
-// values represent a new seed for hashing an index into attribute
-// offsets. Zero indicates not found.
-// Attribute Offsets - Array of 32-bit unsigned values representing offsets into
-// attribute data. Attribute offsets can be iterated to do a
-// full survey of resources in the image. Offset of zero
-// indicates no attributes.
-// Attribute Data - Bytes representing compact attribute data for locations. (See
-// comments in ImageLocation.)
-// Strings - Collection of zero terminated UTF-8 strings used by the index and
-// image meta data. Each string is accessed by offset. Each string is
-// unique. Offset zero is reserved for the empty string.
-//
-// Note that the memory mapped index assumes 32 bit alignment of each component
-// in the index.
-//
-// Endianness of an image.
-// An image booted by hotspot is always in native endian. However, it is possible
-// to read (by the JDK) in alternate endian format. Primarily, this is during
-// cross platform scenarios. Ex, where javac needs to read an embedded image
-// to access classes for crossing compilation.
-//
-
-class ImageFileReader; // forward declaration
-
-// Manage image file string table.
-class ImageStrings VALUE_OBJ_CLASS_SPEC {
-private:
- u1* _data; // Data bytes for strings.
- u4 _size; // Number of bytes in the string table.
-public:
- enum {
- // Not found result from find routine.
- NOT_FOUND = -1,
- // Prime used to generate hash for Perfect Hashing.
- HASH_MULTIPLIER = 0x01000193
- };
-
- ImageStrings(u1* data, u4 size) : _data(data), _size(size) {}
-
- // Return the UTF-8 string beginning at offset.
- inline const char* get(u4 offset) const {
- guarantee(offset < _size, "offset exceeds string table size");
- return (const char*)(_data + offset);
- }
-
- // Compute the Perfect Hashing hash code for the supplied UTF-8 string.
- inline static u4 hash_code(const char* string) {
- return hash_code(string, HASH_MULTIPLIER);
- }
-
- // Compute the Perfect Hashing hash code for the supplied string, starting at seed.
- static s4 hash_code(const char* string, s4 seed);
-
- // Match up a string in a perfect hash table. Result still needs validation
- // for precise match.
- static s4 find(Endian* endian, const char* name, s4* redirect, u4 length);
-
- // Test to see if UTF-8 string begins with the start UTF-8 string. If so,
- // return non-NULL address of remaining portion of string. Otherwise, return
- // NULL. Used to test sections of a path without copying from image string
- // table.
- static const char* starts_with(const char* string, const char* start);
-
- // Test to see if UTF-8 string begins with start char. If so, return non-NULL
- // address of remaining portion of string. Otherwise, return NULL. Used
- // to test a character of a path without copying.
- inline static const char* starts_with(const char* string, const char ch) {
- return *string == ch ? string + 1 : NULL;
- }
-};
-
-// Manage image file location attribute data. Within an image, a location's
-// attributes are compressed into a stream of bytes. An attribute stream is
-// composed of individual attribute sequences. Each attribute sequence begins with
-// a header byte containing the attribute 'kind' (upper 5 bits of header) and the
-// 'length' less 1 (lower 3 bits of header) of bytes that follow containing the
-// attribute value. Attribute values present as most significant byte first.
-//
-// Ex. Container offset (ATTRIBUTE_OFFSET) 0x33562 would be represented as 0x22
-// (kind = 4, length = 3), 0x03, 0x35, 0x62.
-//
-// An attribute stream is terminated with a header kind of ATTRIBUTE_END (header
-// byte of zero.)
-//
-// ImageLocation inflates the stream into individual values stored in the long
-// array _attributes. This allows an attribute value can be quickly accessed by
-// direct indexing. Unspecified values default to zero.
-//
-// Notes:
-// - Even though ATTRIBUTE_END is used to mark the end of the attribute stream,
-// streams will contain zero byte values to represent lesser significant bits.
-// Thus, detecting a zero byte is not sufficient to detect the end of an attribute
-// stream.
-// - ATTRIBUTE_OFFSET represents the number of bytes from the beginning of the region
-// storing the resources. Thus, in an image this represents the number of bytes
-// after the index.
-// - Currently, compressed resources are represented by having a non-zero
-// ATTRIBUTE_COMPRESSED value. This represents the number of bytes stored in the
-// image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the
-// inflated resource in memory. If the ATTRIBUTE_COMPRESSED is zero then the value
-// of ATTRIBUTE_UNCOMPRESSED represents both the number of bytes in the image and
-// in memory. In the future, additional compression techniques will be used and
-// represented differently.
-// - Package strings include trailing slash and extensions include prefix period.
-//
-class ImageLocation VALUE_OBJ_CLASS_SPEC {
-public:
- enum {
- ATTRIBUTE_END, // End of attribute stream marker
- ATTRIBUTE_MODULE, // String table offset of module name
- ATTRIBUTE_PARENT, // String table offset of resource path parent
- ATTRIBUTE_BASE, // String table offset of resource path base
- ATTRIBUTE_EXTENSION, // String table offset of resource path extension
- ATTRIBUTE_OFFSET, // Container byte offset of resource
- ATTRIBUTE_COMPRESSED, // In image byte size of the compressed resource
- ATTRIBUTE_UNCOMPRESSED, // In memory byte size of the uncompressed resource
- ATTRIBUTE_COUNT // Number of attribute kinds
- };
-
-private:
- // Values of inflated attributes.
- u8 _attributes[ATTRIBUTE_COUNT];
-
- // Return the attribute value number of bytes.
- inline static u1 attribute_length(u1 data) {
- return (data & 0x7) + 1;
- }
-
- // Return the attribute kind.
- inline static u1 attribute_kind(u1 data) {
- u1 kind = data >> 3;
- guarantee(kind < ATTRIBUTE_COUNT, "invalid attribute kind");
- return kind;
- }
-
- // Return the attribute length.
- inline static u8 attribute_value(u1* data, u1 n) {
- guarantee(0 < n && n <= 8, "invalid attribute value length");
- u8 value = 0;
- // Most significant bytes first.
- for (u1 i = 0; i < n; i++) {
- value <<= 8;
- value |= data[i];
- }
- return value;
- }
-
-public:
- ImageLocation() {
- clear_data();
- }
-
- ImageLocation(u1* data) {
- clear_data();
- set_data(data);
- }
-
- // Inflates the attribute stream into individual values stored in the long
- // array _attributes. This allows an attribute value to be quickly accessed by
- // direct indexing. Unspecified values default to zero.
- void set_data(u1* data);
-
- // Zero all attribute values.
- void clear_data();
-
- // Retrieve an attribute value from the inflated array.
- inline u8 get_attribute(u1 kind) const {
- guarantee(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT, "invalid attribute kind");
- return _attributes[kind];
- }
-
- // Retrieve an attribute string value from the inflated array.
- inline const char* get_attribute(u4 kind, const ImageStrings& strings) const {
- return strings.get((u4)get_attribute(kind));
- }
-};
-
-//
-// NOTE: needs revision.
-// Each loader requires set of module meta data to identify which modules and
-// packages are managed by that loader. Currently, there is one image file per
-// builtin loader, so only one module meta data resource per file.
-//
-// Each element in the module meta data is a native endian 4 byte integer. Note
-// that entries with zero offsets for string table entries should be ignored (
-// padding for hash table lookup.)
-//
-// Format:
-// Count of package to module entries
-// Count of module to package entries
-// Perfect Hash redirect table[Count of package to module entries]
-// Package to module entries[Count of package to module entries]
-// Offset to package name in string table
-// Offset to module name in string table
-// Perfect Hash redirect table[Count of module to package entries]
-// Module to package entries[Count of module to package entries]
-// Offset to module name in string table
-// Count of packages in module
-// Offset to first package in packages table
-// Packages[]
-// Offset to package name in string table
-//
-// Manage the image module meta data.
-class ImageModuleData : public CHeapObj<mtClass> {
- class Header VALUE_OBJ_CLASS_SPEC {
- private:
- u4 _ptm_count; // Count of package to module entries
- u4 _mtp_count; // Count of module to package entries
- public:
- inline u4 ptm_count(Endian* endian) const { return endian->get(_ptm_count); }
- inline u4 mtp_count(Endian* endian) const { return endian->get(_mtp_count); }
- };
-
- // Hashtable entry
- class HashData VALUE_OBJ_CLASS_SPEC {
- private:
- u4 _name_offset; // Name offset in string table
- public:
- inline s4 name_offset(Endian* endian) const { return endian->get(_name_offset); }
- };
-
- // Package to module hashtable entry
- class PTMData : public HashData {
- private:
- u4 _module_name_offset; // Module name offset in string table
- public:
- inline s4 module_name_offset(Endian* endian) const { return endian->get(_module_name_offset); }
- };
-
- // Module to package hashtable entry
- class MTPData : public HashData {
- private:
- u4 _package_count; // Number of packages in module
- u4 _package_offset; // Offset in package list
- public:
- inline u4 package_count(Endian* endian) const { return endian->get(_package_count); }
- inline u4 package_offset(Endian* endian) const { return endian->get(_package_offset); }
- };
-
- const ImageFileReader* _image_file; // Source image file
- Endian* _endian; // Endian handler
- ImageStrings _strings; // Image file strings
- u1* _data; // Module data resource data
- u8 _data_size; // Size of resource data
- Header* _header; // Module data header
- s4* _ptm_redirect; // Package to module hashtable redirect
- PTMData* _ptm_data; // Package to module data
- s4* _mtp_redirect; // Module to packages hashtable redirect
- MTPData* _mtp_data; // Module to packages data
- s4* _mtp_packages; // Package data (name offsets)
-
- // Return a string from the string table.
- inline const char* get_string(u4 offset) {
- return _strings.get(offset);
- }
-
- inline u4 mtp_package(u4 index) {
- return _endian->get(_mtp_packages[index]);
- }
-
-public:
- ImageModuleData(const ImageFileReader* image_file, const char* module_data_name);
- ~ImageModuleData();
-
- // Return the name of the module data resource.
- static void module_data_name(char* buffer, const char* image_file_name);
-
- // Return the module in which a package resides. Returns NULL if not found.
- const char* package_to_module(const char* package_name);
-
- // Returns all the package names in a module. Returns NULL if module not found.
- GrowableArray<const char*>* module_to_packages(const char* module_name);
-};
-
-// Image file header, starting at offset 0.
-class ImageHeader VALUE_OBJ_CLASS_SPEC {
-private:
- u4 _magic; // Image file marker
- u4 _version; // Image file major version number
- u4 _flags; // Image file flags
- u4 _resource_count; // Number of resources in file
- u4 _table_length; // Number of slots in index tables
- u4 _locations_size; // Number of bytes in attribute table
- u4 _strings_size; // Number of bytes in string table
-
-public:
- u4 magic() const { return _magic; }
- u4 magic(Endian* endian) const { return endian->get(_magic); }
- void set_magic(Endian* endian, u4 magic) { return endian->set(_magic, magic); }
-
- u4 major_version(Endian* endian) const { return endian->get(_version) >> 16; }
- u4 minor_version(Endian* endian) const { return endian->get(_version) & 0xFFFF; }
- void set_version(Endian* endian, u4 major_version, u4 minor_version) {
- return endian->set(_version, major_version << 16 | minor_version);
- }
-
- u4 flags(Endian* endian) const { return endian->get(_flags); }
- void set_flags(Endian* endian, u4 value) { return endian->set(_flags, value); }
-
- u4 resource_count(Endian* endian) const { return endian->get(_resource_count); }
- void set_resource_count(Endian* endian, u4 count) { return endian->set(_resource_count, count); }
-
- u4 table_length(Endian* endian) const { return endian->get(_table_length); }
- void set_table_length(Endian* endian, u4 count) { return endian->set(_table_length, count); }
-
- u4 locations_size(Endian* endian) const { return endian->get(_locations_size); }
- void set_locations_size(Endian* endian, u4 size) { return endian->set(_locations_size, size); }
-
- u4 strings_size(Endian* endian) const { return endian->get(_strings_size); }
- void set_strings_size(Endian* endian, u4 size) { return endian->set(_strings_size, size); }
-};
-
-// Max path length limit independent of platform. Windows max path is 1024,
-// other platforms use 4096. The JCK fails several tests when 1024 is used.
-#define IMAGE_MAX_PATH 4096
-
-// Manage the image file.
-// ImageFileReader manages the content of an image file.
-// Initially, the header of the image file is read for validation. If valid,
-// values in the header are used calculate the size of the image index. The
-// index is then memory mapped to allow load on demand and sharing. The
-// -XX:+MemoryMapImage flag determines if the entire file is loaded (server use.)
-// An image can be used by Hotspot and multiple reference points in the JDK, thus
-// it is desirable to share a reader. To accomodate sharing, a share table is
-// defined (see ImageFileReaderTable in imageFile.cpp) To track the number of
-// uses, ImageFileReader keeps a use count (_use). Use is incremented when
-// 'opened' by reference point and decremented when 'closed'. Use of zero
-// leads the ImageFileReader to be actually closed and discarded.
-class ImageFileReader : public CHeapObj<mtClass> {
-private:
- // Manage a number of image files such that an image can be shared across
- // multiple uses (ex. loader.)
- static GrowableArray<ImageFileReader*>* _reader_table;
-
- char* _name; // Name of image
- s4 _use; // Use count
- int _fd; // File descriptor
- Endian* _endian; // Endian handler
- u8 _file_size; // File size in bytes
- ImageHeader _header; // Image header
- size_t _index_size; // Total size of index
- u1* _index_data; // Raw index data
- s4* _redirect_table; // Perfect hash redirect table
- u4* _offsets_table; // Location offset table
- u1* _location_bytes; // Location attributes
- u1* _string_bytes; // String table
-
- ImageFileReader(const char* name, bool big_endian);
- ~ImageFileReader();
-
- // Compute number of bytes in image file index.
- inline u8 index_size() {
- return sizeof(ImageHeader) +
- table_length() * sizeof(u4) * 2 + locations_size() + strings_size();
- }
-
-public:
- enum {
- // Image file marker.
- IMAGE_MAGIC = 0xCAFEDADA,
- // Endian inverted Image file marker.
- IMAGE_MAGIC_INVERT = 0xDADAFECA,
- // Image file major version number.
- MAJOR_VERSION = 1,
- // Image file minor version number.
- MINOR_VERSION = 0
- };
-
- // Open an image file, reuse structure if file already open.
- static ImageFileReader* open(const char* name, bool big_endian = Endian::is_big_endian());
-
- // Close an image file if the file is not in use elsewhere.
- static void close(ImageFileReader *reader);
-
- // Return an id for the specifed ImageFileReader.
- static u8 readerToID(ImageFileReader *reader);
-
- // Validate the image id.
- static bool idCheck(u8 id);
-
- // Return an id for the specifed ImageFileReader.
- static ImageFileReader* idToReader(u8 id);
-
- // Open image file for read access.
- bool open();
-
- // Close image file.
- void close();
-
- // Read directly from the file.
- bool read_at(u1* data, u8 size, u8 offset) const;
-
- inline Endian* endian() const { return _endian; }
-
- // Retrieve name of image file.
- inline const char* name() const {
- return _name;
- }
-
- // Retrieve size of image file.
- inline u8 file_size() const {
- return _file_size;
- }
-
- // Return first address of index data.
- inline u1* get_index_address() const {
- return _index_data;
- }
-
- // Return first address of resource data.
- inline u1* get_data_address() const {
- return _index_data + _index_size;
- }
-
- // Get the size of the index data.
- size_t get_index_size() const {
- return _index_size;
- }
-
- inline u4 table_length() const {
- return _header.table_length(_endian);
- }
-
- inline u4 locations_size() const {
- return _header.locations_size(_endian);
- }
-
- inline u4 strings_size()const {
- return _header.strings_size(_endian);
- }
-
- inline u4* offsets_table() const {
- return _offsets_table;
- }
-
- // Increment use count.
- inline void inc_use() {
- _use++;
- }
-
- // Decrement use count.
- inline bool dec_use() {
- return --_use == 0;
- }
-
- // Return a string table accessor.
- inline const ImageStrings get_strings() const {
- return ImageStrings(_string_bytes, _header.strings_size(_endian));
- }
-
- // Return location attribute stream at offset.
- inline u1* get_location_offset_data(u4 offset) const {
- guarantee((u4)offset < _header.locations_size(_endian),
- "offset exceeds location attributes size");
- return offset != 0 ? _location_bytes + offset : NULL;
- }
-
- // Return location attribute stream for location i.
- inline u1* get_location_data(u4 index) const {
- guarantee((u4)index < _header.table_length(_endian),
- "index exceeds location count");
- u4 offset = _endian->get(_offsets_table[index]);
-
- return get_location_offset_data(offset);
- }
-
- // Find the location attributes associated with the path. Returns true if
- // the location is found, false otherwise.
- bool find_location(const char* path, ImageLocation& location) const;
-
- // Assemble the location path.
- void location_path(ImageLocation& location, char* path, size_t max) const;
-
- // Verify that a found location matches the supplied path.
- bool verify_location(ImageLocation& location, const char* path) const;
-
- // Return the resource for the supplied path.
- void get_resource(ImageLocation& location, u1* uncompressed_data) const;
-};
-#endif // SHARE_VM_CLASSFILE_IMAGEFILE_HPP
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -29,7 +29,6 @@
#include "classfile/vmSymbols.hpp"
#include "code/debugInfo.hpp"
#include "code/pcDesc.hpp"
-#include "compiler/compilerOracle.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/jimage.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "jni.h"
+
+// Opaque reference to a JImage file.
+class JImageFile;
+// Opaque reference to an image file resource location.
+typedef jlong JImageLocationRef;
+
+// Max path length limit independent of platform. Windows max path is 1024,
+// other platforms use 4096. The JCK fails several tests when 1024 is used.
+#define JIMAGE_MAX_PATH 4096
+
+// JImage Error Codes
+
+// The image file is not prefixed with 0xCAFEDADA
+#define JIMAGE_BAD_MAGIC (-1)
+// The image file does not have a compatible (translatable) version
+#define JIMAGE_BAD_VERSION (-2)
+// The image file content is malformed
+#define JIMAGE_CORRUPTED (-3)
+
+/*
+ * JImageOpen - Given the supplied full path file name, open an image file. This
+ * function will also initialize tables and retrieve meta-data necessary to
+ * satisfy other functions in the API. If the image file has been previously
+ * open, a new open request will share memory and resources used by the previous
+ * open. A call to JImageOpen should be balanced by a call to JImageClose, to
+ * release memory and resources used. If the image file is not found or cannot
+ * be open, then NULL is returned and error will contain a reason for the
+ * failure; a positive value for a system error number, negative for a jimage
+ * specific error (see JImage Error Codes.)
+ *
+ * Ex.
+ * jint error;
+ * JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error);
+ * if (image == NULL) {
+ * tty->print_cr("JImage failed to open: %d", error);
+ * ...
+ * }
+ * ...
+ */
+
+extern "C" JImageFile* JIMAGE_Open(const char *name, jint* error);
+
+typedef JImageFile* (*JImageOpen_t)(const char *name, jint* error);
+
+/*
+ * JImageClose - Given the supplied open image file (see JImageOpen), release
+ * memory and resources used by the open file and close the file. If the image
+ * file is shared by other uses, release and close is deferred until the last use
+ * is also closed.
+ *
+ * Ex.
+ * (*JImageClose)(image);
+ */
+
+extern "C" void JIMAGE_Close(JImageFile* jimage);
+
+typedef void (*JImageClose_t)(JImageFile* jimage);
+
+
+/*
+ * JImagePackageToModule - Given an open image file (see JImageOpen) and the name
+ * of a package, return the name of module where the package resides. If the
+ * package does not exist in the image file, the function returns NULL.
+ * The resulting string does/should not have to be released. All strings are
+ * utf-8, zero byte terminated.
+ *
+ * Ex.
+ * const char* package = (*JImagePackageToModule)(image, "java/lang");
+ * tty->print_cr(package);
+ * —> java.base
+ */
+
+extern "C" const char * JIMAGE_PackageToModule(JImageFile* jimage, const char* package_name);
+
+typedef const char* (*JImagePackageToModule_t)(JImageFile* jimage, const char* package_name);
+
+
+/*
+ * JImageFindResource - Given an open image file (see JImageOpen), a module
+ * name, a version string and the name of a class/resource, return location
+ * information describing the resource and its size. If no resource is found, the
+ * function returns JIMAGE_NOT_FOUND and the value of size is undefined.
+ * The version number should be "9.0" and is not used in locating the resource.
+ * The resulting location does/should not have to be released.
+ * All strings are utf-8, zero byte terminated.
+ *
+ * Ex.
+ * jlong size;
+ * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size);
+ */
+extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* jimage,
+ const char* module_name, const char* version, const char* name,
+ jlong* size);
+
+typedef JImageLocationRef(*JImageFindResource_t)(JImageFile* jimage,
+ const char* module_name, const char* version, const char* name,
+ jlong* size);
+
+
+/*
+ * JImageGetResource - Given an open image file (see JImageOpen), a resource’s
+ * location information (see JImageFindResource), a buffer of appropriate
+ * size and the size, retrieve the bytes associated with the
+ * resource. If the size is less than the resource size then the read is truncated.
+ * If the size is greater than the resource size then the remainder of the buffer
+ * is zero filled. The function will return the actual size of the resource.
+ *
+ * Ex.
+ * jlong size;
+ * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size);
+ * char* buffer = new char[size];
+ * (*JImageGetResource)(image, location, buffer, size);
+ */
+extern "C" jlong JIMAGE_GetResource(JImageFile* jimage, JImageLocationRef location,
+ char* buffer, jlong size);
+
+typedef jlong(*JImageGetResource_t)(JImageFile* jimage, JImageLocationRef location,
+ char* buffer, jlong size);
+
+
+/*
+ * JImageResourceIterator - Given an open image file (see JImageOpen), a visitor
+ * function and a visitor argument, iterator through each of the image's resources.
+ * The visitor function is called with the image file, the module name, the
+ * package name, the base name, the extension and the visitor argument. The return
+ * value of the visitor function should be true, unless an early iteration exit is
+ * required. All strings are utf-8, zero byte terminated.file.
+ *
+ * Ex.
+ * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg) {
+ * if (strcmp(extension, “class”) == 0) {
+ * char path[JIMAGE_MAX_PATH];
+ * Thread* THREAD = Thread::current();
+ * jio_snprintf(path, JIMAGE_MAX_PATH - 1, "/%s/%s", package, name);
+ * ClassLoader::compile_the_world_in(path, (Handle)arg, THREAD);
+ * return !HAS_PENDING_EXCEPTION;
+ * }
+ * return true;
+ * }
+ * (*JImageResourceIterator)(image, ctw_visitor, loader);
+ */
+
+typedef bool (*JImageResourceVisitor_t)(JImageFile* jimage,
+ const char* module_name, const char* version, const char* package,
+ const char* name, const char* extension, void* arg);
+
+extern "C" void JIMAGE_ResourceIterator(JImageFile* jimage,
+ JImageResourceVisitor_t visitor, void *arg);
+
+typedef void (*JImageResourceIterator_t)(JImageFile* jimage,
+ JImageResourceVisitor_t visitor, void* arg);
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -625,6 +625,10 @@
case vmIntrinsics::_updateDirectByteBufferCRC32C:
if (!UseCRC32CIntrinsics) return true;
break;
+ case vmIntrinsics::_updateBytesAdler32:
+ case vmIntrinsics::_updateByteBufferAdler32:
+ if (!UseAdler32Intrinsics) return true;
+ break;
case vmIntrinsics::_copyMemory:
if (!InlineArrayCopy || !InlineUnsafeOps) return true;
break;
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -927,6 +927,12 @@
do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_C_name, updateByteBuffer_signature, F_S) \
do_name( updateDirectByteBuffer_C_name, "updateDirectByteBuffer") \
\
+ /* support for java.util.zip.Adler32 */ \
+ do_class(java_util_zip_Adler32, "java/util/zip/Adler32") \
+ do_intrinsic(_updateBytesAdler32, java_util_zip_Adler32, updateBytes_C_name, updateBytes_signature, F_SN) \
+ do_intrinsic(_updateByteBufferAdler32, java_util_zip_Adler32, updateByteBuffer_A_name, updateByteBuffer_signature, F_SN) \
+ do_name( updateByteBuffer_A_name, "updateByteBuffer") \
+ \
/* support for sun.misc.Unsafe */ \
do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \
\
--- a/hotspot/src/share/vm/code/codeCache.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/code/codeCache.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -745,13 +745,12 @@
void CodeCache::gc_epilogue() {
assert_locked_or_safepoint(CodeCache_lock);
- NMethodIterator iter;
- while(iter.next()) {
- nmethod* nm = iter.method();
- if (!nm->is_zombie()) {
- if (needs_cache_clean()) {
- // Clean ICs of unloaded nmethods as well because they may reference other
- // unloaded nmethods that may be flushed earlier in the sweeper cycle.
+ NOT_DEBUG(if (needs_cache_clean())) {
+ NMethodIterator iter;
+ while(iter.next_alive()) {
+ nmethod* nm = iter.method();
+ assert(!nm->is_unloaded(), "Tautology");
+ DEBUG_ONLY(if (needs_cache_clean())) {
nm->cleanup_inline_caches();
}
DEBUG_ONLY(nm->verify());
--- a/hotspot/src/share/vm/code/compiledIC.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/code/compiledIC.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -287,6 +287,7 @@
assert( is_c1_method ||
!is_monomorphic ||
is_optimized() ||
+ !caller->is_alive() ||
(cached_metadata() != NULL && cached_metadata()->is_klass()), "sanity check");
#endif // ASSERT
return is_monomorphic;
@@ -321,7 +322,7 @@
}
-void CompiledIC::set_to_clean() {
+void CompiledIC::set_to_clean(bool in_use) {
assert(SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->is_locked() , "MT-unsafe call");
if (TraceInlineCacheClearing || TraceICs) {
tty->print_cr("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address()));
@@ -337,7 +338,7 @@
// A zombie transition will always be safe, since the metadata has already been set to NULL, so
// we only need to patch the destination
- bool safe_transition = is_optimized() || SafepointSynchronize::is_at_safepoint();
+ bool safe_transition = !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint();
if (safe_transition) {
// Kill any leftover stub we might have too
--- a/hotspot/src/share/vm/code/compiledIC.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/code/compiledIC.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -214,7 +214,7 @@
//
// They all takes a TRAP argument, since they can cause a GC if the inline-cache buffer is full.
//
- void set_to_clean();
+ void set_to_clean(bool in_use = true);
void set_to_monomorphic(CompiledICInfo& info);
void clear_ic_stub();
--- a/hotspot/src/share/vm/code/nmethod.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/code/nmethod.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -848,10 +848,10 @@
if (st != NULL) {
ttyLocker ttyl;
if (WizardMode) {
- CompileTask::print_compilation(st, this, msg, /*short_form:*/ true);
+ CompileTask::print(st, this, msg, /*short_form:*/ true);
st->print_cr(" (" INTPTR_FORMAT ")", this);
} else {
- CompileTask::print_compilation(st, this, msg, /*short_form:*/ false);
+ CompileTask::print(st, this, msg, /*short_form:*/ false);
}
}
}
@@ -1050,7 +1050,7 @@
if( cb != NULL && cb->is_nmethod() ) {
nmethod* nm = (nmethod*)cb;
// Clean inline caches pointing to zombie, non-entrant and unloaded methods
- if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean();
+ if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(is_alive());
}
break;
}
@@ -1150,7 +1150,7 @@
// Tell if a non-entrant method can be converted to a zombie (i.e.,
// there are no activations on the stack, not in use by the VM,
// and not in use by the ServiceThread)
-bool nmethod::can_not_entrant_be_converted() {
+bool nmethod::can_convert_to_zombie() {
assert(is_not_entrant(), "must be a non-entrant method");
// Since the nmethod sweeper only does partial sweep the sweeper's traversal
--- a/hotspot/src/share/vm/code/nmethod.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/code/nmethod.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -577,7 +577,7 @@
// See comment at definition of _last_seen_on_stack
void mark_as_seen_on_stack();
- bool can_not_entrant_be_converted();
+ bool can_convert_to_zombie();
// Evolution support. We make old (discarded) compiled methods point to new Method*s.
void set_method(Method* method) { _method = method; }
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -157,7 +157,6 @@
CompileQueue* CompileBroker::_c2_compile_queue = NULL;
CompileQueue* CompileBroker::_c1_compile_queue = NULL;
-
class CompilationLog : public StringEventLog {
public:
CompilationLog() : StringEventLog("Compilation events") {
@@ -167,7 +166,7 @@
StringLogMessage lm;
stringStream sstr = lm.stream();
// msg.time_stamp().update_to(tty->time_stamp().ticks());
- task->print_compilation(&sstr, NULL, true, false);
+ task->print(&sstr, NULL, true, false);
log(thread, "%s", (const char*)lm);
}
@@ -233,371 +232,6 @@
}
}
-
-CompileTask* CompileTask::_task_free_list = NULL;
-#ifdef ASSERT
-int CompileTask::_num_allocated_tasks = 0;
-#endif
-/**
- * Allocate a CompileTask, from the free list if possible.
- */
-CompileTask* CompileTask::allocate() {
- MutexLocker locker(CompileTaskAlloc_lock);
- CompileTask* task = NULL;
-
- if (_task_free_list != NULL) {
- task = _task_free_list;
- _task_free_list = task->next();
- task->set_next(NULL);
- } else {
- task = new CompileTask();
- DEBUG_ONLY(_num_allocated_tasks++;)
- assert (WhiteBoxAPI || _num_allocated_tasks < 10000, "Leaking compilation tasks?");
- task->set_next(NULL);
- task->set_is_free(true);
- }
- assert(task->is_free(), "Task must be free.");
- task->set_is_free(false);
- return task;
-}
-
-
-/**
- * Add a task to the free list.
- */
-void CompileTask::free(CompileTask* task) {
- MutexLocker locker(CompileTaskAlloc_lock);
- if (!task->is_free()) {
- task->set_code(NULL);
- assert(!task->lock()->is_locked(), "Should not be locked when freed");
- JNIHandles::destroy_global(task->_method_holder);
- JNIHandles::destroy_global(task->_hot_method_holder);
-
- task->set_is_free(true);
- task->set_next(_task_free_list);
- _task_free_list = task;
- }
-}
-
-void CompileTask::initialize(int compile_id,
- methodHandle method,
- int osr_bci,
- int comp_level,
- methodHandle hot_method,
- int hot_count,
- const char* comment,
- bool is_blocking) {
- assert(!_lock->is_locked(), "bad locking");
-
- _compile_id = compile_id;
- _method = method();
- _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder());
- _osr_bci = osr_bci;
- _is_blocking = is_blocking;
- _comp_level = comp_level;
- _num_inlined_bytecodes = 0;
-
- _is_complete = false;
- _is_success = false;
- _code_handle = NULL;
-
- _hot_method = NULL;
- _hot_method_holder = NULL;
- _hot_count = hot_count;
- _time_queued = 0; // tidy
- _comment = comment;
- _failure_reason = NULL;
-
- if (LogCompilation) {
- _time_queued = os::elapsed_counter();
- if (hot_method.not_null()) {
- if (hot_method == method) {
- _hot_method = _method;
- } else {
- _hot_method = hot_method();
- // only add loader or mirror if different from _method_holder
- _hot_method_holder = JNIHandles::make_global(hot_method->method_holder()->klass_holder());
- }
- }
- }
-
- _next = NULL;
-}
-
-// ------------------------------------------------------------------
-// CompileTask::code/set_code
-nmethod* CompileTask::code() const {
- if (_code_handle == NULL) return NULL;
- return _code_handle->code();
-}
-void CompileTask::set_code(nmethod* nm) {
- if (_code_handle == NULL && nm == NULL) return;
- guarantee(_code_handle != NULL, "");
- _code_handle->set_code(nm);
- if (nm == NULL) _code_handle = NULL; // drop the handle also
-}
-
-void CompileTask::mark_on_stack() {
- // Mark these methods as something redefine classes cannot remove.
- _method->set_on_stack(true);
- if (_hot_method != NULL) {
- _hot_method->set_on_stack(true);
- }
-}
-
-// RedefineClasses support
-void CompileTask::metadata_do(void f(Metadata*)) {
- f(method());
- if (hot_method() != NULL && hot_method() != method()) {
- f(hot_method());
- }
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_line_on_error
-//
-// This function is called by fatal error handler when the thread
-// causing troubles is a compiler thread.
-//
-// Do not grab any lock, do not allocate memory.
-//
-// Otherwise it's the same as CompileTask::print_line()
-//
-void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
- // print compiler name
- st->print("%s:", CompileBroker::compiler_name(comp_level()));
- print_compilation(st);
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_line
-void CompileTask::print_tty() {
- ttyLocker ttyl; // keep the following output all in one block
- // print compiler name if requested
- if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
- print_compilation(tty);
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_compilation_impl
-void CompileTask::print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
- bool is_osr_method, int osr_bci, bool is_blocking,
- const char* msg, bool short_form, bool cr) {
- if (!short_form) {
- st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp
- }
- st->print("%4d ", compile_id); // print compilation number
-
- // For unloaded methods the transition to zombie occurs after the
- // method is cleared so it's impossible to report accurate
- // information for that case.
- bool is_synchronized = false;
- bool has_exception_handler = false;
- bool is_native = false;
- if (method != NULL) {
- is_synchronized = method->is_synchronized();
- has_exception_handler = method->has_exception_handler();
- is_native = method->is_native();
- }
- // method attributes
- const char compile_type = is_osr_method ? '%' : ' ';
- const char sync_char = is_synchronized ? 's' : ' ';
- const char exception_char = has_exception_handler ? '!' : ' ';
- const char blocking_char = is_blocking ? 'b' : ' ';
- const char native_char = is_native ? 'n' : ' ';
-
- // print method attributes
- st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
-
- if (TieredCompilation) {
- if (comp_level != -1) st->print("%d ", comp_level);
- else st->print("- ");
- }
- st->print(" "); // more indent
-
- if (method == NULL) {
- st->print("(method)");
- } else {
- method->print_short_name(st);
- if (is_osr_method) {
- st->print(" @ %d", osr_bci);
- }
- if (method->is_native())
- st->print(" (native)");
- else
- st->print(" (%d bytes)", method->code_size());
- }
-
- if (msg != NULL) {
- st->print(" %s", msg);
- }
- if (cr) {
- st->cr();
- }
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_inlining
-void CompileTask::print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
- // 1234567
- st->print(" "); // print timestamp
- // 1234
- st->print(" "); // print compilation number
-
- // method attributes
- if (method->is_loaded()) {
- const char sync_char = method->is_synchronized() ? 's' : ' ';
- const char exception_char = method->has_exception_handlers() ? '!' : ' ';
- const char monitors_char = method->has_monitor_bytecodes() ? 'm' : ' ';
-
- // print method attributes
- st->print(" %c%c%c ", sync_char, exception_char, monitors_char);
- } else {
- // %s!bn
- st->print(" "); // print method attributes
- }
-
- if (TieredCompilation) {
- st->print(" ");
- }
- st->print(" "); // more indent
- st->print(" "); // initial inlining indent
-
- for (int i = 0; i < inline_level; i++) st->print(" ");
-
- st->print("@ %d ", bci); // print bci
- method->print_short_name(st);
- if (method->is_loaded())
- st->print(" (%d bytes)", method->code_size());
- else
- st->print(" (not loaded)");
-
- if (msg != NULL) {
- st->print(" %s", msg);
- }
- st->cr();
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_inline_indent
-void CompileTask::print_inline_indent(int inline_level, outputStream* st) {
- // 1234567
- st->print(" "); // print timestamp
- // 1234
- st->print(" "); // print compilation number
- // %s!bn
- st->print(" "); // print method attributes
- if (TieredCompilation) {
- st->print(" ");
- }
- st->print(" "); // more indent
- st->print(" "); // initial inlining indent
- for (int i = 0; i < inline_level; i++) st->print(" ");
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_compilation
-void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form, bool cr) {
- bool is_osr_method = osr_bci() != InvocationEntryBci;
- print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr);
-}
-
-// ------------------------------------------------------------------
-// CompileTask::log_task
-void CompileTask::log_task(xmlStream* log) {
- Thread* thread = Thread::current();
- methodHandle method(thread, this->method());
- ResourceMark rm(thread);
-
- // <task compiler='Cx' id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
- log->print(" compiler='%s' compile_id='%d'", _comp_level <= CompLevel_full_profile ? "C1" : "C2", _compile_id);
- if (_osr_bci != CompileBroker::standard_entry_bci) {
- log->print(" compile_kind='osr'"); // same as nmethod::compile_kind
- } // else compile_kind='c2c'
- if (!method.is_null()) log->method(method);
- if (_osr_bci != CompileBroker::standard_entry_bci) {
- log->print(" osr_bci='%d'", _osr_bci);
- }
- if (_comp_level != CompLevel_highest_tier) {
- log->print(" level='%d'", _comp_level);
- }
- if (_is_blocking) {
- log->print(" blocking='1'");
- }
- log->stamp();
-}
-
-
-// ------------------------------------------------------------------
-// CompileTask::log_task_queued
-void CompileTask::log_task_queued() {
- Thread* thread = Thread::current();
- ttyLocker ttyl;
- ResourceMark rm(thread);
-
- xtty->begin_elem("task_queued");
- log_task(xtty);
- if (_comment != NULL) {
- xtty->print(" comment='%s'", _comment);
- }
- if (_hot_method != NULL) {
- methodHandle hot(thread, _hot_method);
- methodHandle method(thread, _method);
- if (hot() != method()) {
- xtty->method(hot);
- }
- }
- if (_hot_count != 0) {
- xtty->print(" hot_count='%d'", _hot_count);
- }
- xtty->end_elem();
-}
-
-
-// ------------------------------------------------------------------
-// CompileTask::log_task_start
-void CompileTask::log_task_start(CompileLog* log) {
- log->begin_head("task");
- log_task(log);
- log->end_head();
-}
-
-
-// ------------------------------------------------------------------
-// CompileTask::log_task_done
-void CompileTask::log_task_done(CompileLog* log) {
- Thread* thread = Thread::current();
- methodHandle method(thread, this->method());
- ResourceMark rm(thread);
-
- if (!_is_success) {
- const char* reason = _failure_reason != NULL ? _failure_reason : "unknown";
- log->elem("failure reason='%s'", reason);
- }
-
- // <task_done ... stamp='1.234'> </task>
- nmethod* nm = code();
- log->begin_elem("task_done success='%d' nmsize='%d' count='%d'",
- _is_success, nm == NULL ? 0 : nm->content_size(),
- method->invocation_count());
- int bec = method->backedge_count();
- if (bec != 0) log->print(" backedge_count='%d'", bec);
- // Note: "_is_complete" is about to be set, but is not.
- if (_num_inlined_bytecodes != 0) {
- log->print(" inlined_bytes='%d'", _num_inlined_bytecodes);
- }
- log->stamp();
- log->end_elem();
- log->tail("task");
- log->clear_identities(); // next task will have different CI
- if (log->unflushed_count() > 2000) {
- log->flush();
- }
- log->mark_file_end();
-}
-
-
-
/**
* Add a CompileTask to a CompileQueue.
*/
@@ -807,7 +441,7 @@
st->print_cr("Empty");
} else {
while (task != NULL) {
- task->print_compilation(st, NULL, true, true);
+ task->print(st, NULL, true, true);
task = task->next();
}
}
@@ -1349,7 +983,7 @@
#ifndef TIERED
// seems like an assert of dubious value
assert(comp_level == CompLevel_highest_tier,
- "all OSR compiles are assumed to be at a single compilation lavel");
+ "all OSR compiles are assumed to be at a single compilation level");
#endif // TIERED
// We accept a higher level osr method
nmethod* nm = method->lookup_osr_nmethod_for(osr_bci, comp_level, false);
@@ -2037,7 +1671,7 @@
FormatBufferResource msg = retry_message != NULL ?
err_msg_res("COMPILE SKIPPED: %s (%s)", ci_env.failure_reason(), retry_message) :
err_msg_res("COMPILE SKIPPED: %s", ci_env.failure_reason());
- task->print_compilation(tty, msg);
+ task->print(tty, msg);
}
} else {
task->mark_success();
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -27,127 +27,12 @@
#include "ci/compilerInterface.hpp"
#include "compiler/abstractCompiler.hpp"
+#include "compiler/compileTask.hpp"
#include "runtime/perfData.hpp"
class nmethod;
class nmethodLocker;
-// CompileTask
-//
-// An entry in the compile queue. It represents a pending or current
-// compilation.
-class CompileTask : public CHeapObj<mtCompiler> {
- friend class VMStructs;
-
- private:
- static CompileTask* _task_free_list;
-#ifdef ASSERT
- static int _num_allocated_tasks;
-#endif
-
- Monitor* _lock;
- uint _compile_id;
- Method* _method;
- jobject _method_holder;
- int _osr_bci;
- bool _is_complete;
- bool _is_success;
- bool _is_blocking;
- int _comp_level;
- int _num_inlined_bytecodes;
- nmethodLocker* _code_handle; // holder of eventual result
- CompileTask* _next, *_prev;
- bool _is_free;
- // Fields used for logging why the compilation was initiated:
- jlong _time_queued; // in units of os::elapsed_counter()
- Method* _hot_method; // which method actually triggered this task
- jobject _hot_method_holder;
- int _hot_count; // information about its invocation counter
- const char* _comment; // more info about the task
- const char* _failure_reason;
-
- public:
- CompileTask() {
- _lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock");
- }
-
- void initialize(int compile_id, methodHandle method, int osr_bci, int comp_level,
- methodHandle hot_method, int hot_count, const char* comment,
- bool is_blocking);
-
- static CompileTask* allocate();
- static void free(CompileTask* task);
-
- int compile_id() const { return _compile_id; }
- Method* method() const { return _method; }
- Method* hot_method() const { return _hot_method; }
- int osr_bci() const { return _osr_bci; }
- bool is_complete() const { return _is_complete; }
- bool is_blocking() const { return _is_blocking; }
- bool is_success() const { return _is_success; }
-
- nmethodLocker* code_handle() const { return _code_handle; }
- void set_code_handle(nmethodLocker* l) { _code_handle = l; }
- nmethod* code() const; // _code_handle->code()
- void set_code(nmethod* nm); // _code_handle->set_code(nm)
-
- Monitor* lock() const { return _lock; }
-
- void mark_complete() { _is_complete = true; }
- void mark_success() { _is_success = true; }
-
- int comp_level() { return _comp_level;}
- void set_comp_level(int comp_level) { _comp_level = comp_level;}
-
- int num_inlined_bytecodes() const { return _num_inlined_bytecodes; }
- void set_num_inlined_bytecodes(int n) { _num_inlined_bytecodes = n; }
-
- CompileTask* next() const { return _next; }
- void set_next(CompileTask* next) { _next = next; }
- CompileTask* prev() const { return _prev; }
- void set_prev(CompileTask* prev) { _prev = prev; }
- bool is_free() const { return _is_free; }
- void set_is_free(bool val) { _is_free = val; }
-
- // RedefineClasses support
- void metadata_do(void f(Metadata*));
-
-private:
- static void print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
- bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
- const char* msg = NULL, bool short_form = false, bool cr = true);
-
-public:
- void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true);
- static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) {
- print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(),
- nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false,
- msg, short_form, cr);
- }
-
- static void print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
- static void print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
- print_inlining(tty, method, inline_level, bci, msg);
- }
-
- // Redefine Classes support
- void mark_on_stack();
-
- static void print_inline_indent(int inline_level, outputStream* st = tty);
-
- void print_tty();
- void print_line_on_error(outputStream* st, char* buf, int buflen);
-
- void log_task(xmlStream* log);
- void log_task_queued();
- void log_task_start(CompileLog* log);
- void log_task_done(CompileLog* log);
-
- void set_failure_reason(const char* reason) {
- _failure_reason = reason;
- }
-};
-
// CompilerCounters
//
// Per Compiler Performance Counters.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/compileTask.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,391 @@
+/*
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "compiler/compileTask.hpp"
+#include "compiler/compileLog.hpp"
+#include "compiler/compileBroker.hpp"
+
+CompileTask* CompileTask::_task_free_list = NULL;
+#ifdef ASSERT
+int CompileTask::_num_allocated_tasks = 0;
+#endif
+
+/**
+ * Allocate a CompileTask, from the free list if possible.
+ */
+CompileTask* CompileTask::allocate() {
+ MutexLocker locker(CompileTaskAlloc_lock);
+ CompileTask* task = NULL;
+
+ if (_task_free_list != NULL) {
+ task = _task_free_list;
+ _task_free_list = task->next();
+ task->set_next(NULL);
+ } else {
+ task = new CompileTask();
+ DEBUG_ONLY(_num_allocated_tasks++;)
+ assert (WhiteBoxAPI || _num_allocated_tasks < 10000, "Leaking compilation tasks?");
+ task->set_next(NULL);
+ task->set_is_free(true);
+ }
+ assert(task->is_free(), "Task must be free.");
+ task->set_is_free(false);
+ return task;
+}
+
+/**
+* Add a task to the free list.
+*/
+
+void CompileTask::free(CompileTask* task) {
+ MutexLocker locker(CompileTaskAlloc_lock);
+ if (!task->is_free()) {
+ task->set_code(NULL);
+ assert(!task->lock()->is_locked(), "Should not be locked when freed");
+ JNIHandles::destroy_global(task->_method_holder);
+ JNIHandles::destroy_global(task->_hot_method_holder);
+
+ task->set_is_free(true);
+ task->set_next(_task_free_list);
+ _task_free_list = task;
+ }
+}
+
+
+void CompileTask::initialize(int compile_id,
+ methodHandle method,
+ int osr_bci,
+ int comp_level,
+ methodHandle hot_method,
+ int hot_count,
+ const char* comment,
+ bool is_blocking) {
+ assert(!_lock->is_locked(), "bad locking");
+
+ _compile_id = compile_id;
+ _method = method();
+ _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder());
+ _osr_bci = osr_bci;
+ _is_blocking = is_blocking;
+ _comp_level = comp_level;
+ _num_inlined_bytecodes = 0;
+
+ _is_complete = false;
+ _is_success = false;
+ _code_handle = NULL;
+
+ _hot_method = NULL;
+ _hot_method_holder = NULL;
+ _hot_count = hot_count;
+ _time_queued = 0; // tidy
+ _comment = comment;
+ _failure_reason = NULL;
+
+ if (LogCompilation) {
+ _time_queued = os::elapsed_counter();
+ if (hot_method.not_null()) {
+ if (hot_method == method) {
+ _hot_method = _method;
+ } else {
+ _hot_method = hot_method();
+ // only add loader or mirror if different from _method_holder
+ _hot_method_holder = JNIHandles::make_global(hot_method->method_holder()->klass_holder());
+ }
+ }
+ }
+
+ _next = NULL;
+}
+
+// ------------------------------------------------------------------
+// CompileTask::code/set_code
+//
+nmethod* CompileTask::code() const {
+ if (_code_handle == NULL) return NULL;
+ return _code_handle->code();
+}
+
+void CompileTask::set_code(nmethod* nm) {
+ if (_code_handle == NULL && nm == NULL) return;
+ guarantee(_code_handle != NULL, "");
+ _code_handle->set_code(nm);
+ if (nm == NULL) _code_handle = NULL; // drop the handle also
+}
+
+void CompileTask::mark_on_stack() {
+ // Mark these methods as something redefine classes cannot remove.
+ _method->set_on_stack(true);
+ if (_hot_method != NULL) {
+ _hot_method->set_on_stack(true);
+ }
+}
+
+// RedefineClasses support
+void CompileTask::metadata_do(void f(Metadata*)) {
+ f(method());
+ if (hot_method() != NULL && hot_method() != method()) {
+ f(hot_method());
+ }
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_line_on_error
+//
+// This function is called by fatal error handler when the thread
+// causing troubles is a compiler thread.
+//
+// Do not grab any lock, do not allocate memory.
+//
+// Otherwise it's the same as CompileTask::print_line()
+//
+void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
+ // print compiler name
+ st->print("%s:", CompileBroker::compiler_name(comp_level()));
+ print(st);
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_tty
+void CompileTask::print_tty() {
+ ttyLocker ttyl; // keep the following output all in one block
+ // print compiler name if requested
+ if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
+ print(tty);
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_impl
+void CompileTask::print_impl(outputStream* st, Method* method, int compile_id, int comp_level,
+ bool is_osr_method, int osr_bci, bool is_blocking,
+ const char* msg, bool short_form, bool cr) {
+ if (!short_form) {
+ st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp
+ }
+ st->print("%4d ", compile_id); // print compilation number
+
+ // For unloaded methods the transition to zombie occurs after the
+ // method is cleared so it's impossible to report accurate
+ // information for that case.
+ bool is_synchronized = false;
+ bool has_exception_handler = false;
+ bool is_native = false;
+ if (method != NULL) {
+ is_synchronized = method->is_synchronized();
+ has_exception_handler = method->has_exception_handler();
+ is_native = method->is_native();
+ }
+ // method attributes
+ const char compile_type = is_osr_method ? '%' : ' ';
+ const char sync_char = is_synchronized ? 's' : ' ';
+ const char exception_char = has_exception_handler ? '!' : ' ';
+ const char blocking_char = is_blocking ? 'b' : ' ';
+ const char native_char = is_native ? 'n' : ' ';
+
+ // print method attributes
+ st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
+
+ if (TieredCompilation) {
+ if (comp_level != -1) st->print("%d ", comp_level);
+ else st->print("- ");
+ }
+ st->print(" "); // more indent
+
+ if (method == NULL) {
+ st->print("(method)");
+ } else {
+ method->print_short_name(st);
+ if (is_osr_method) {
+ st->print(" @ %d", osr_bci);
+ }
+ if (method->is_native())
+ st->print(" (native)");
+ else
+ st->print(" (%d bytes)", method->code_size());
+ }
+
+ if (msg != NULL) {
+ st->print(" %s", msg);
+ }
+ if (cr) {
+ st->cr();
+ }
+}
+
+void CompileTask::print_inline_indent(int inline_level, outputStream* st) {
+ // 1234567
+ st->print(" "); // print timestamp
+ // 1234
+ st->print(" "); // print compilation number
+ // %s!bn
+ st->print(" "); // print method attributes
+ if (TieredCompilation) {
+ st->print(" ");
+ }
+ st->print(" "); // more indent
+ st->print(" "); // initial inlining indent
+ for (int i = 0; i < inline_level; i++) st->print(" ");
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_compilation
+void CompileTask::print(outputStream* st, const char* msg, bool short_form, bool cr) {
+ bool is_osr_method = osr_bci() != InvocationEntryBci;
+ print_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr);
+}
+
+// ------------------------------------------------------------------
+// CompileTask::log_task
+void CompileTask::log_task(xmlStream* log) {
+ Thread* thread = Thread::current();
+ methodHandle method(thread, this->method());
+ ResourceMark rm(thread);
+
+ // <task id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
+ log->print(" compile_id='%d'", _compile_id);
+ if (_osr_bci != CompileBroker::standard_entry_bci) {
+ log->print(" compile_kind='osr'"); // same as nmethod::compile_kind
+ } // else compile_kind='c2c'
+ if (!method.is_null()) log->method(method);
+ if (_osr_bci != CompileBroker::standard_entry_bci) {
+ log->print(" osr_bci='%d'", _osr_bci);
+ }
+ if (_comp_level != CompLevel_highest_tier) {
+ log->print(" level='%d'", _comp_level);
+ }
+ if (_is_blocking) {
+ log->print(" blocking='1'");
+ }
+ log->stamp();
+}
+
+// ------------------------------------------------------------------
+// CompileTask::log_task_queued
+void CompileTask::log_task_queued() {
+ Thread* thread = Thread::current();
+ ttyLocker ttyl;
+ ResourceMark rm(thread);
+
+ xtty->begin_elem("task_queued");
+ log_task(xtty);
+ if (_comment != NULL) {
+ xtty->print(" comment='%s'", _comment);
+ }
+ if (_hot_method != NULL) {
+ methodHandle hot(thread, _hot_method);
+ methodHandle method(thread, _method);
+ if (hot() != method()) {
+ xtty->method(hot);
+ }
+ }
+ if (_hot_count != 0) {
+ xtty->print(" hot_count='%d'", _hot_count);
+ }
+ xtty->end_elem();
+}
+
+
+// ------------------------------------------------------------------
+// CompileTask::log_task_start
+void CompileTask::log_task_start(CompileLog* log) {
+ log->begin_head("task");
+ log_task(log);
+ log->end_head();
+}
+
+
+// ------------------------------------------------------------------
+// CompileTask::log_task_done
+void CompileTask::log_task_done(CompileLog* log) {
+ Thread* thread = Thread::current();
+ methodHandle method(thread, this->method());
+ ResourceMark rm(thread);
+
+ if (!_is_success) {
+ const char* reason = _failure_reason != NULL ? _failure_reason : "unknown";
+ log->elem("failure reason='%s'", reason);
+ }
+
+ // <task_done ... stamp='1.234'> </task>
+ nmethod* nm = code();
+ log->begin_elem("task_done success='%d' nmsize='%d' count='%d'",
+ _is_success, nm == NULL ? 0 : nm->content_size(),
+ method->invocation_count());
+ int bec = method->backedge_count();
+ if (bec != 0) log->print(" backedge_count='%d'", bec);
+ // Note: "_is_complete" is about to be set, but is not.
+ if (_num_inlined_bytecodes != 0) {
+ log->print(" inlined_bytes='%d'", _num_inlined_bytecodes);
+ }
+ log->stamp();
+ log->end_elem();
+ log->clear_identities(); // next task will have different CI
+ log->tail("task");
+ if (log->unflushed_count() > 2000) {
+ log->flush();
+ }
+ log->mark_file_end();
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_inlining
+void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
+ // 1234567
+ st->print(" "); // print timestamp
+ // 1234
+ st->print(" "); // print compilation number
+
+ // method attributes
+ if (method->is_loaded()) {
+ const char sync_char = method->is_synchronized() ? 's' : ' ';
+ const char exception_char = method->has_exception_handlers() ? '!' : ' ';
+ const char monitors_char = method->has_monitor_bytecodes() ? 'm' : ' ';
+
+ // print method attributes
+ st->print(" %c%c%c ", sync_char, exception_char, monitors_char);
+ } else {
+ // %s!bn
+ st->print(" "); // print method attributes
+ }
+
+ if (TieredCompilation) {
+ st->print(" ");
+ }
+ st->print(" "); // more indent
+ st->print(" "); // initial inlining indent
+
+ for (int i = 0; i < inline_level; i++) st->print(" ");
+
+ st->print("@ %d ", bci); // print bci
+ method->print_short_name(st);
+ if (method->is_loaded())
+ st->print(" (%d bytes)", method->code_size());
+ else
+ st->print(" (not loaded)");
+
+ if (msg != NULL) {
+ st->print(" %s", msg);
+ }
+ st->cr();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/compileTask.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1998, 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 SHARE_VM_COMPILER_COMPILETASK_HPP
+#define SHARE_VM_COMPILER_COMPILETASK_HPP
+
+#include "code/nmethod.hpp"
+#include "ci/ciMethod.hpp"
+#include "compiler/compileLog.hpp"
+#include "memory/allocation.inline.hpp"
+#include "utilities/xmlstream.hpp"
+
+// CompileTask
+//
+// An entry in the compile queue. It represents a pending or current
+// compilation.
+
+class CompileTask : public CHeapObj<mtCompiler> {
+ friend class VMStructs;
+
+ private:
+ static CompileTask* _task_free_list;
+#ifdef ASSERT
+ static int _num_allocated_tasks;
+#endif
+
+ Monitor* _lock;
+ uint _compile_id;
+ Method* _method;
+ jobject _method_holder;
+ int _osr_bci;
+ bool _is_complete;
+ bool _is_success;
+ bool _is_blocking;
+ int _comp_level;
+ int _num_inlined_bytecodes;
+ nmethodLocker* _code_handle; // holder of eventual result
+ CompileTask* _next, *_prev;
+ bool _is_free;
+ // Fields used for logging why the compilation was initiated:
+ jlong _time_queued; // in units of os::elapsed_counter()
+ Method* _hot_method; // which method actually triggered this task
+ jobject _hot_method_holder;
+ int _hot_count; // information about its invocation counter
+ const char* _comment; // more info about the task
+ const char* _failure_reason;
+
+ public:
+ CompileTask() {
+ _lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock");
+ }
+
+ void initialize(int compile_id, methodHandle method, int osr_bci, int comp_level,
+ methodHandle hot_method, int hot_count, const char* comment,
+ bool is_blocking);
+
+ static CompileTask* allocate();
+ static void free(CompileTask* task);
+
+ int compile_id() const { return _compile_id; }
+ Method* method() const { return _method; }
+ Method* hot_method() const { return _hot_method; }
+ int osr_bci() const { return _osr_bci; }
+ bool is_complete() const { return _is_complete; }
+ bool is_blocking() const { return _is_blocking; }
+ bool is_success() const { return _is_success; }
+
+ nmethodLocker* code_handle() const { return _code_handle; }
+ void set_code_handle(nmethodLocker* l) { _code_handle = l; }
+ nmethod* code() const; // _code_handle->code()
+ void set_code(nmethod* nm); // _code_handle->set_code(nm)
+
+ Monitor* lock() const { return _lock; }
+
+ void mark_complete() { _is_complete = true; }
+ void mark_success() { _is_success = true; }
+
+ int comp_level() { return _comp_level;}
+ void set_comp_level(int comp_level) { _comp_level = comp_level;}
+
+ int num_inlined_bytecodes() const { return _num_inlined_bytecodes; }
+ void set_num_inlined_bytecodes(int n) { _num_inlined_bytecodes = n; }
+
+ CompileTask* next() const { return _next; }
+ void set_next(CompileTask* next) { _next = next; }
+ CompileTask* prev() const { return _prev; }
+ void set_prev(CompileTask* prev) { _prev = prev; }
+ bool is_free() const { return _is_free; }
+ void set_is_free(bool val) { _is_free = val; }
+
+ // RedefineClasses support
+ void metadata_do(void f(Metadata*));
+ void mark_on_stack();
+
+private:
+ static void print_impl(outputStream* st, Method* method, int compile_id, int comp_level,
+ bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
+ const char* msg = NULL, bool short_form = false, bool cr = true);
+
+public:
+ void print(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true);
+ static void print(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) {
+ print_impl(st, nm->method(), nm->compile_id(), nm->comp_level(),
+ nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false,
+ msg, short_form, cr);
+ }
+
+ static void print_inline_indent(int inline_level, outputStream* st = tty);
+
+ void print_tty();
+ void print_line_on_error(outputStream* st, char* buf, int buflen);
+
+ void log_task(xmlStream* log);
+ void log_task_queued();
+ void log_task_start(CompileLog* log);
+ void log_task_done(CompileLog* log);
+
+ void set_failure_reason(const char* reason) {
+ _failure_reason = reason;
+ }
+
+ bool check_break_at_flags();
+
+ static void print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
+ static void print_inlining_tty(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
+ print_inlining_inner(tty, method, inline_level, bci, msg);
+ }
+};
+
+#endif // SHARE_VM_COMPILER_COMPILETASK_HPP
--- a/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -66,7 +66,8 @@
virtual void do_klass(Klass* k);
void do_klass_nv(Klass* k);
- virtual void do_class_loader_data(ClassLoaderData* cld);
+ virtual void do_cld(ClassLoaderData* cld) { do_cld_nv(cld); }
+ void do_cld_nv(ClassLoaderData* cld);
};
class MarkRefsIntoClosure: public MetadataAwareOopsInGenClosure {
--- a/hotspot/src/share/vm/gc/cms/cmsOopClosures.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/cmsOopClosures.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -50,11 +50,11 @@
inline void MetadataAwareOopsInGenClosure::do_klass_nv(Klass* k) {
ClassLoaderData* cld = k->class_loader_data();
- do_class_loader_data(cld);
+ do_cld_nv(cld);
}
inline void MetadataAwareOopsInGenClosure::do_klass(Klass* k) { do_klass_nv(k); }
-inline void MetadataAwareOopsInGenClosure::do_class_loader_data(ClassLoaderData* cld) {
+inline void MetadataAwareOopsInGenClosure::do_cld_nv(ClassLoaderData* cld) {
assert(_klass_closure._oop_closure == this, "Must be");
bool claim = true; // Must claim the class loader data before processing.
--- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -702,7 +702,7 @@
!_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \
oop(bottom)) && \
!_collector->CMSCollector::is_dead_obj(oop(bottom))) { \
- size_t word_sz = oop(bottom)->oop_iterate(cl, mr); \
+ size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \
bottom += _cfls->adjustObjectSize(word_sz); \
} else { \
bottom += _cfls->CompactibleFreeListSpace::block_size(bottom); \
@@ -729,7 +729,7 @@
!_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks( \
oop(bottom)) && \
!_collector->CMSCollector::is_dead_obj(oop(bottom))) { \
- size_t word_sz = oop(bottom)->oop_iterate(cl, mr); \
+ size_t word_sz = oop(bottom)->oop_iterate_size(cl, mr); \
bottom += _cfls->adjustObjectSize(word_sz); \
} else { \
bottom += _cfls->CompactibleFreeListSpace::block_size_nopar(bottom); \
@@ -2989,7 +2989,7 @@
assert(task_size > CardTableModRefBS::card_size_in_words &&
(task_size % CardTableModRefBS::card_size_in_words == 0),
"Otherwise arithmetic below would be incorrect");
- MemRegion span = _gen->reserved();
+ MemRegion span = _old_gen->reserved();
if (low != NULL) {
if (span.contains(low)) {
// Align low down to a card boundary so that
--- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -99,7 +99,7 @@
BlockOffsetArrayNonContigSpace _bt;
CMSCollector* _collector;
- ConcurrentMarkSweepGeneration* _gen;
+ ConcurrentMarkSweepGeneration* _old_gen;
// Data structures for free blocks (used during allocation/sweeping)
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -212,7 +212,7 @@
use_adaptive_freelists,
dictionaryChoice);
NOT_PRODUCT(debug_cms_space = _cmsSpace;)
- _cmsSpace->_gen = this;
+ _cmsSpace->_old_gen = this;
_gc_stats = new CMSGCStats();
@@ -359,13 +359,13 @@
(size_t) _cms_gen->gc_stats()->avg_promoted()->padded_average());
if (cms_free > expected_promotion) {
// Start a cms collection if there isn't enough space to promote
- // for the next minor collection. Use the padded average as
+ // for the next young collection. Use the padded average as
// a safety factor.
cms_free -= expected_promotion;
// Adjust by the safety factor.
double cms_free_dbl = (double)cms_free;
- double cms_adjustment = (100.0 - CMSIncrementalSafetyFactor)/100.0;
+ double cms_adjustment = (100.0 - CMSIncrementalSafetyFactor) / 100.0;
// Apply a further correction factor which tries to adjust
// for recent occurance of concurrent mode failures.
cms_adjustment = cms_adjustment * cms_free_adjustment_factor(cms_free);
@@ -531,7 +531,7 @@
if (CMSConcurrentMTEnabled) {
if (FLAG_IS_DEFAULT(ConcGCThreads)) {
// just for now
- FLAG_SET_DEFAULT(ConcGCThreads, (ParallelGCThreads + 3)/4);
+ FLAG_SET_DEFAULT(ConcGCThreads, (ParallelGCThreads + 3) / 4);
}
if (ConcGCThreads > 1) {
_conc_workers = new YieldingFlexibleWorkGang("CMS Thread",
@@ -592,7 +592,7 @@
_cmsGen ->init_initiating_occupancy(CMSInitiatingOccupancyFraction, CMSTriggerRatio);
// Clip CMSBootstrapOccupancy between 0 and 100.
- _bootstrap_occupancy = ((double)CMSBootstrapOccupancy)/(double)100;
+ _bootstrap_occupancy = CMSBootstrapOccupancy / 100.0;
// Now tell CMS generations the identity of their collector
ConcurrentMarkSweepGeneration::set_collector(this);
@@ -613,7 +613,7 @@
_end_addr = gch->end_addr();
assert(_young_gen != NULL, "no _young_gen");
_eden_chunk_index = 0;
- _eden_chunk_capacity = (_young_gen->max_capacity()+CMSSamplingGrain)/CMSSamplingGrain;
+ _eden_chunk_capacity = (_young_gen->max_capacity() + CMSSamplingGrain) / CMSSamplingGrain;
_eden_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, _eden_chunk_capacity, mtGC);
}
@@ -795,29 +795,22 @@
size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
gclog_or_tty->print_cr("\nFrom compute_new_size: ");
gclog_or_tty->print_cr(" Free fraction %f", free_percentage);
- gclog_or_tty->print_cr(" Desired free fraction %f",
- desired_free_percentage);
- gclog_or_tty->print_cr(" Maximum free fraction %f",
- maximum_free_percentage);
- gclog_or_tty->print_cr(" Capacity " SIZE_FORMAT, capacity()/1000);
- gclog_or_tty->print_cr(" Desired capacity " SIZE_FORMAT,
- desired_capacity/1000);
+ gclog_or_tty->print_cr(" Desired free fraction %f", desired_free_percentage);
+ gclog_or_tty->print_cr(" Maximum free fraction %f", maximum_free_percentage);
+ gclog_or_tty->print_cr(" Capacity " SIZE_FORMAT, capacity() / 1000);
+ gclog_or_tty->print_cr(" Desired capacity " SIZE_FORMAT, desired_capacity / 1000);
GenCollectedHeap* gch = GenCollectedHeap::heap();
assert(gch->is_old_gen(this), "The CMS generation should always be the old generation");
size_t young_size = gch->young_gen()->capacity();
gclog_or_tty->print_cr(" Young gen size " SIZE_FORMAT, young_size / 1000);
- gclog_or_tty->print_cr(" unsafe_max_alloc_nogc " SIZE_FORMAT,
- unsafe_max_alloc_nogc()/1000);
- gclog_or_tty->print_cr(" contiguous available " SIZE_FORMAT,
- contiguous_available()/1000);
- gclog_or_tty->print_cr(" Expand by " SIZE_FORMAT " (bytes)",
- expand_bytes);
+ gclog_or_tty->print_cr(" unsafe_max_alloc_nogc " SIZE_FORMAT, unsafe_max_alloc_nogc() / 1000);
+ gclog_or_tty->print_cr(" contiguous available " SIZE_FORMAT, contiguous_available() / 1000);
+ gclog_or_tty->print_cr(" Expand by " SIZE_FORMAT " (bytes)", expand_bytes);
}
// safe if expansion fails
expand_for_gc_cause(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio);
if (PrintGCDetails && Verbose) {
- gclog_or_tty->print_cr(" Expanded free fraction %f",
- ((double) free()) / capacity());
+ gclog_or_tty->print_cr(" Expanded free fraction %f", ((double) free()) / capacity());
}
} else {
size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage));
@@ -834,16 +827,14 @@
return cmsSpace()->freelistLock();
}
-HeapWord* ConcurrentMarkSweepGeneration::allocate(size_t size,
- bool tlab) {
+HeapWord* ConcurrentMarkSweepGeneration::allocate(size_t size, bool tlab) {
CMSSynchronousYieldRequest yr;
- MutexLockerEx x(freelistLock(),
- Mutex::_no_safepoint_check_flag);
+ MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
return have_lock_and_allocate(size, tlab);
}
HeapWord* ConcurrentMarkSweepGeneration::have_lock_and_allocate(size_t size,
- bool tlab /* ignored */) {
+ bool tlab /* ignored */) {
assert_lock_strong(freelistLock());
size_t adjustedSize = CompactibleFreeListSpace::adjustObjectSize(size);
HeapWord* res = cmsSpace()->allocate(adjustedSize);
@@ -2426,7 +2417,7 @@
gch->gen_process_roots(&srs,
GenCollectedHeap::OldGen,
- true, // younger gens are roots
+ true, // young gen as roots
GenCollectedHeap::ScanningOption(roots_scanning_options()),
should_unload_classes(),
¬Older,
@@ -2498,7 +2489,7 @@
gch->gen_process_roots(&srs,
GenCollectedHeap::OldGen,
- true, // younger gens are roots
+ true, // young gen as roots
GenCollectedHeap::ScanningOption(roots_scanning_options()),
should_unload_classes(),
¬Older,
@@ -2952,12 +2943,7 @@
assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped");
assert(_collectorState == InitialMarking, "just checking");
- // If there has not been a GC[n-1] since last GC[n] cycle completed,
- // precede our marking with a collection of all
- // younger generations to keep floating garbage to a minimum.
- // XXX: we won't do this for now -- it's an optimization to be done later.
-
- // already have locks
+ // Already have locks.
assert_lock_strong(bitMapLock());
assert(_markBitMap.isAllClear(), "was reset at end of previous cycle");
@@ -3027,7 +3013,7 @@
gch->gen_process_roots(&srs,
GenCollectedHeap::OldGen,
- true, // younger gens are roots
+ true, // young gen as roots
GenCollectedHeap::ScanningOption(roots_scanning_options()),
should_unload_classes(),
¬Older,
@@ -3037,7 +3023,7 @@
}
// Clear mod-union table; it will be dirtied in the prologue of
- // CMS generation per each younger generation collection.
+ // CMS generation per each young generation collection.
assert(_modUnionTable.isAllClear(),
"Was cleared in most recent final checkpoint phase"
@@ -3057,7 +3043,7 @@
// assert(!SafepointSynchronize::is_at_safepoint(),
// "inconsistent argument?");
// However that wouldn't be right, because it's possible that
- // a safepoint is indeed in progress as a younger generation
+ // a safepoint is indeed in progress as a young generation
// stop-the-world GC happens even as we mark in this generation.
assert(_collectorState == Marking, "inconsistent state?");
check_correct_thread_executing();
@@ -3065,7 +3051,7 @@
// Weak ref discovery note: We may be discovering weak
// refs in this generation concurrent (but interleaved) with
- // weak ref discovery by a younger generation collector.
+ // weak ref discovery by the young generation collector.
CMSTokenSyncWithLocks ts(true, bitMapLock());
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
@@ -3095,7 +3081,7 @@
// Note that when we do a marking step we need to hold the
// bit map lock -- recall that direct allocation (by mutators)
- // and promotion (by younger generation collectors) is also
+ // and promotion (by the young generation collector) is also
// marking the bit map. [the so-called allocate live policy.]
// Because the implementation of bit map marking is not
// robust wrt simultaneous marking of bits in the same word,
@@ -4049,7 +4035,7 @@
// one of these methods, please check the other method too.
size_t CMSCollector::preclean_mod_union_table(
- ConcurrentMarkSweepGeneration* gen,
+ ConcurrentMarkSweepGeneration* old_gen,
ScanMarkedObjectsAgainCarefullyClosure* cl) {
verify_work_stacks_empty();
verify_overflow_empty();
@@ -4064,10 +4050,10 @@
// generation, but we might potentially miss cards when the
// generation is rapidly expanding while we are in the midst
// of precleaning.
- HeapWord* startAddr = gen->reserved().start();
- HeapWord* endAddr = gen->reserved().end();
-
- cl->setFreelistLock(gen->freelistLock()); // needed for yielding
+ HeapWord* startAddr = old_gen->reserved().start();
+ HeapWord* endAddr = old_gen->reserved().end();
+
+ cl->setFreelistLock(old_gen->freelistLock()); // needed for yielding
size_t numDirtyCards, cumNumDirtyCards;
HeapWord *nextAddr, *lastAddr;
@@ -4109,7 +4095,7 @@
HeapWord* stop_point = NULL;
stopTimer();
// Potential yield point
- CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
+ CMSTokenSyncWithLocks ts(true, old_gen->freelistLock(),
bitMapLock());
startTimer();
{
@@ -4117,7 +4103,7 @@
verify_overflow_empty();
sample_eden();
stop_point =
- gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl);
+ old_gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl);
}
if (stop_point != NULL) {
// The careful iteration stopped early either because it found an
@@ -4152,15 +4138,15 @@
// below are largely identical; if you need to modify
// one of these methods, please check the other method too.
-size_t CMSCollector::preclean_card_table(ConcurrentMarkSweepGeneration* gen,
+size_t CMSCollector::preclean_card_table(ConcurrentMarkSweepGeneration* old_gen,
ScanMarkedObjectsAgainCarefullyClosure* cl) {
// strategy: it's similar to precleamModUnionTable above, in that
// we accumulate contiguous ranges of dirty cards, mark these cards
// precleaned, then scan the region covered by these cards.
- HeapWord* endAddr = (HeapWord*)(gen->_virtual_space.high());
- HeapWord* startAddr = (HeapWord*)(gen->_virtual_space.low());
-
- cl->setFreelistLock(gen->freelistLock()); // needed for yielding
+ HeapWord* endAddr = (HeapWord*)(old_gen->_virtual_space.high());
+ HeapWord* startAddr = (HeapWord*)(old_gen->_virtual_space.low());
+
+ cl->setFreelistLock(old_gen->freelistLock()); // needed for yielding
size_t numDirtyCards, cumNumDirtyCards;
HeapWord *lastAddr, *nextAddr;
@@ -4197,13 +4183,13 @@
if (!dirtyRegion.is_empty()) {
stopTimer();
- CMSTokenSyncWithLocks ts(true, gen->freelistLock(), bitMapLock());
+ CMSTokenSyncWithLocks ts(true, old_gen->freelistLock(), bitMapLock());
startTimer();
sample_eden();
verify_work_stacks_empty();
verify_overflow_empty();
HeapWord* stop_point =
- gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl);
+ old_gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl);
if (stop_point != NULL) {
assert((_collectorState == AbortablePreclean && should_abort_preclean()),
"Should only be AbortablePreclean.");
@@ -4623,7 +4609,7 @@
ResourceMark rm;
GrowableArray<ClassLoaderData*>* array = ClassLoaderDataGraph::new_clds();
for (int i = 0; i < array->length(); i++) {
- par_mrias_cl.do_class_loader_data(array->at(i));
+ par_mrias_cl.do_cld_nv(array->at(i));
}
// We don't need to keep track of new CLDs anymore.
@@ -5086,7 +5072,7 @@
// preclean phase did of eden, plus the [two] tasks of
// scanning the [two] survivor spaces. Further fine-grain
// parallelization of the scanning of the survivor spaces
- // themselves, and of precleaning of the younger gen itself
+ // themselves, and of precleaning of the young gen itself
// is deferred to the future.
initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
@@ -5177,7 +5163,7 @@
gch->gen_process_roots(&srs,
GenCollectedHeap::OldGen,
- true, // younger gens as roots
+ true, // young gen as roots
GenCollectedHeap::ScanningOption(roots_scanning_options()),
should_unload_classes(),
&mrias_cl,
@@ -5199,7 +5185,7 @@
ResourceMark rm;
GrowableArray<ClassLoaderData*>* array = ClassLoaderDataGraph::new_clds();
for (int i = 0; i < array->length(); i++) {
- mrias_cl.do_class_loader_data(array->at(i));
+ mrias_cl.do_cld_nv(array->at(i));
}
// We don't need to keep track of new CLDs anymore.
@@ -5661,7 +5647,7 @@
}
}
-void CMSCollector::sweepWork(ConcurrentMarkSweepGeneration* gen) {
+void CMSCollector::sweepWork(ConcurrentMarkSweepGeneration* old_gen) {
// We iterate over the space(s) underlying this generation,
// checking the mark bit map to see if the bits corresponding
// to specific blocks are marked or not. Blocks that are
@@ -5690,26 +5676,26 @@
// check that we hold the requisite locks
assert(have_cms_token(), "Should hold cms token");
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), "Should possess CMS token to sweep");
- assert_lock_strong(gen->freelistLock());
+ assert_lock_strong(old_gen->freelistLock());
assert_lock_strong(bitMapLock());
assert(!_inter_sweep_timer.is_active(), "Was switched off in an outer context");
assert(_intra_sweep_timer.is_active(), "Was switched on in an outer context");
- gen->cmsSpace()->beginSweepFLCensus((float)(_inter_sweep_timer.seconds()),
- _inter_sweep_estimate.padded_average(),
- _intra_sweep_estimate.padded_average());
- gen->setNearLargestChunk();
+ old_gen->cmsSpace()->beginSweepFLCensus((float)(_inter_sweep_timer.seconds()),
+ _inter_sweep_estimate.padded_average(),
+ _intra_sweep_estimate.padded_average());
+ old_gen->setNearLargestChunk();
{
- SweepClosure sweepClosure(this, gen, &_markBitMap, CMSYield);
- gen->cmsSpace()->blk_iterate_careful(&sweepClosure);
+ SweepClosure sweepClosure(this, old_gen, &_markBitMap, CMSYield);
+ old_gen->cmsSpace()->blk_iterate_careful(&sweepClosure);
// We need to free-up/coalesce garbage/blocks from a
// co-terminal free run. This is done in the SweepClosure
// destructor; so, do not remove this scope, else the
// end-of-sweep-census below will be off by a little bit.
}
- gen->cmsSpace()->sweep_completed();
- gen->cmsSpace()->endSweepFLCensus(sweep_count());
+ old_gen->cmsSpace()->sweep_completed();
+ old_gen->cmsSpace()->endSweepFLCensus(sweep_count());
if (should_unload_classes()) { // unloaded classes this cycle,
_concurrent_cycles_since_last_unload = 0; // ... reset count
} else { // did not unload classes,
@@ -6324,12 +6310,12 @@
// objArrays are precisely marked; restrict scanning
// to dirty cards only.
size = CompactibleFreeListSpace::adjustObjectSize(
- p->oop_iterate(_scanningClosure, mr));
+ p->oop_iterate_size(_scanningClosure, mr));
} else {
// A non-array may have been imprecisely marked; we need
// to scan object in its entirety.
size = CompactibleFreeListSpace::adjustObjectSize(
- p->oop_iterate(_scanningClosure));
+ p->oop_iterate_size(_scanningClosure));
}
#ifdef ASSERT
size_t direct_size =
@@ -6417,7 +6403,7 @@
// Note that we do not yield while we iterate over
// the interior oops of p, pushing the relevant ones
// on our marking stack.
- size_t size = p->oop_iterate(_scanning_closure);
+ size_t size = p->oop_iterate_size(_scanning_closure);
do_yield_check();
// Observe that below, we do not abandon the preclean
// phase as soon as we should; rather we empty the
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -723,7 +723,7 @@
private:
// Support for parallelizing young gen rescan in CMS remark phase
- ParNewGeneration* _young_gen; // the younger gen
+ ParNewGeneration* _young_gen;
HeapWord** _top_addr; // ... Top of Eden
HeapWord** _end_addr; // ... End of Eden
@@ -772,9 +772,9 @@
private:
// Concurrent precleaning work
- size_t preclean_mod_union_table(ConcurrentMarkSweepGeneration* gen,
+ size_t preclean_mod_union_table(ConcurrentMarkSweepGeneration* old_gen,
ScanMarkedObjectsAgainCarefullyClosure* cl);
- size_t preclean_card_table(ConcurrentMarkSweepGeneration* gen,
+ size_t preclean_card_table(ConcurrentMarkSweepGeneration* old_gen,
ScanMarkedObjectsAgainCarefullyClosure* cl);
// Does precleaning work, returning a quantity indicative of
// the amount of "useful work" done.
@@ -797,7 +797,7 @@
void refProcessingWork();
// Concurrent sweeping work
- void sweepWork(ConcurrentMarkSweepGeneration* gen);
+ void sweepWork(ConcurrentMarkSweepGeneration* old_gen);
// (Concurrent) resetting of support data structures
void reset(bool concurrent);
@@ -1120,10 +1120,8 @@
MemRegion used_region_at_save_marks() const;
// Does a "full" (forced) collection invoked on this generation collect
- // all younger generations as well? Note that the second conjunct is a
- // hack to allow the collection of the younger gen first if the flag is
- // set.
- virtual bool full_collects_younger_generations() const {
+ // the young generation as well?
+ virtual bool full_collects_young_generation() const {
return !ScavengeBeforeFullGC;
}
@@ -1153,9 +1151,8 @@
virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes) const;
- // Inform this (non-young) generation that a promotion failure was
- // encountered during a collection of a younger generation that
- // promotes into this generation.
+ // Inform this (old) generation that a promotion failure was
+ // encountered during a collection of the young generation.
virtual void promotion_failure_occurred();
bool should_collect(bool full, size_t size, bool tlab);
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -295,7 +295,7 @@
promoted_bytes = _cms_used_at_gc0_end - _cms_used_at_gc0_begin;
}
- // If the younger gen collections were skipped, then the
+ // If the young gen collection was skipped, then the
// number of promoted bytes will be 0 and adding it to the
// average will incorrectly lessen the average. It is, however,
// also possible that no promotion was needed.
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -39,23 +39,17 @@
// ======= Concurrent Mark Sweep Thread ========
-// The CMS thread is created when Concurrent Mark Sweep is used in the
-// older of two generations in a generational memory system.
+ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::_cmst = NULL;
+CMSCollector* ConcurrentMarkSweepThread::_collector = NULL;
+bool ConcurrentMarkSweepThread::_should_terminate = false;
+int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil;
-ConcurrentMarkSweepThread*
- ConcurrentMarkSweepThread::_cmst = NULL;
-CMSCollector* ConcurrentMarkSweepThread::_collector = NULL;
-bool ConcurrentMarkSweepThread::_should_terminate = false;
-int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil;
+volatile jint ConcurrentMarkSweepThread::_pending_yields = 0;
-volatile jint ConcurrentMarkSweepThread::_pending_yields = 0;
-
-SurrogateLockerThread*
- ConcurrentMarkSweepThread::_slt = NULL;
+SurrogateLockerThread* ConcurrentMarkSweepThread::_slt = NULL;
SurrogateLockerThread::SLT_msg_type
ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty;
-Monitor*
- ConcurrentMarkSweepThread::_sltMonitor = NULL;
+Monitor* ConcurrentMarkSweepThread::_sltMonitor = NULL;
ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
: ConcurrentGCThread() {
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -69,20 +69,28 @@
Stack<oop, mtGC>* overflow_stacks_,
size_t desired_plab_sz_,
ParallelTaskTerminator& term_) :
- _to_space(to_space_), _old_gen(old_gen_), _young_gen(young_gen_), _thread_num(thread_num_),
- _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false),
+ _to_space(to_space_),
+ _old_gen(old_gen_),
+ _young_gen(young_gen_),
+ _thread_num(thread_num_),
+ _work_queue(work_queue_set_->queue(thread_num_)),
+ _to_space_full(false),
_overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL),
_ageTable(false), // false ==> not the global age table, no perf data.
_to_space_alloc_buffer(desired_plab_sz_),
- _to_space_closure(young_gen_, this), _old_gen_closure(young_gen_, this),
- _to_space_root_closure(young_gen_, this), _old_gen_root_closure(young_gen_, this),
+ _to_space_closure(young_gen_, this),
+ _old_gen_closure(young_gen_, this),
+ _to_space_root_closure(young_gen_, this),
+ _old_gen_root_closure(young_gen_, this),
_older_gen_closure(young_gen_, this),
_evacuate_followers(this, &_to_space_closure, &_old_gen_closure,
&_to_space_root_closure, young_gen_, &_old_gen_root_closure,
work_queue_set_, &term_),
- _is_alive_closure(young_gen_), _scan_weak_ref_closure(young_gen_, this),
+ _is_alive_closure(young_gen_),
+ _scan_weak_ref_closure(young_gen_, this),
_keep_alive_closure(&_scan_weak_ref_closure),
- _strong_roots_time(0.0), _term_time(0.0)
+ _strong_roots_time(0.0),
+ _term_time(0.0)
{
#if TASKQUEUE_STATS
_term_attempts = 0;
@@ -90,8 +98,7 @@
_overflow_refill_objs = 0;
#endif // TASKQUEUE_STATS
- _survivor_chunk_array =
- (ChunkArray*) old_gen()->get_data_recorder(thread_num());
+ _survivor_chunk_array = (ChunkArray*) old_gen()->get_data_recorder(thread_num());
_hash_seed = 17; // Might want to take time-based random value.
_start = os::elapsedTime();
_old_gen_closure.set_generation(old_gen_);
@@ -154,7 +161,6 @@
}
}
-
void ParScanThreadState::trim_queues(int max_size) {
ObjToScanQueue* queue = work_queue();
do {
@@ -222,15 +228,12 @@
}
HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) {
-
- // Otherwise, if the object is small enough, try to reallocate the
- // buffer.
+ // If the object is small enough, try to reallocate the buffer.
HeapWord* obj = NULL;
if (!_to_space_full) {
PLAB* const plab = to_space_alloc_buffer();
- Space* const sp = to_space();
- if (word_sz * 100 <
- ParallelGCBufferWastePct * plab->word_sz()) {
+ Space* const sp = to_space();
+ if (word_sz * 100 < ParallelGCBufferWastePct * plab->word_sz()) {
// Is small enough; abandon this buffer and start a new one.
plab->retire();
size_t buf_size = plab->word_sz();
@@ -241,8 +244,7 @@
size_t free_bytes = sp->free();
while(buf_space == NULL && free_bytes >= min_bytes) {
buf_size = free_bytes >> LogHeapWordSize;
- assert(buf_size == (size_t)align_object_size(buf_size),
- "Invariant");
+ assert(buf_size == (size_t)align_object_size(buf_size), "Invariant");
buf_space = sp->par_allocate(buf_size);
free_bytes = sp->free();
}
@@ -262,7 +264,6 @@
// We're used up.
_to_space_full = true;
}
-
} else {
// Too large; allocate the object individually.
obj = sp->par_allocate(word_sz);
@@ -271,7 +272,6 @@
return obj;
}
-
void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj, size_t word_sz) {
to_space_alloc_buffer()->undo_allocation(obj, word_sz);
}
@@ -288,7 +288,7 @@
// Initializes states for the specified number of threads;
ParScanThreadStateSet(int num_threads,
Space& to_space,
- ParNewGeneration& gen,
+ ParNewGeneration& young_gen,
Generation& old_gen,
ObjToScanQueueSet& queue_set,
Stack<oop, mtGC>* overflow_stacks_,
@@ -315,21 +315,25 @@
private:
ParallelTaskTerminator& _term;
- ParNewGeneration& _gen;
+ ParNewGeneration& _young_gen;
Generation& _old_gen;
public:
bool is_valid(int id) const { return id < length(); }
ParallelTaskTerminator* terminator() { return &_term; }
};
-
-ParScanThreadStateSet::ParScanThreadStateSet(
- int num_threads, Space& to_space, ParNewGeneration& gen,
- Generation& old_gen, ObjToScanQueueSet& queue_set,
- Stack<oop, mtGC>* overflow_stacks,
- size_t desired_plab_sz, ParallelTaskTerminator& term)
+ParScanThreadStateSet::ParScanThreadStateSet(int num_threads,
+ Space& to_space,
+ ParNewGeneration& young_gen,
+ Generation& old_gen,
+ ObjToScanQueueSet& queue_set,
+ Stack<oop, mtGC>* overflow_stacks,
+ size_t desired_plab_sz,
+ ParallelTaskTerminator& term)
: ResourceArray(sizeof(ParScanThreadState), num_threads),
- _gen(gen), _old_gen(old_gen), _term(term)
+ _young_gen(young_gen),
+ _old_gen(old_gen),
+ _term(term)
{
assert(num_threads > 0, "sanity check!");
assert(ParGCUseLocalOverflow == (overflow_stacks != NULL),
@@ -337,13 +341,12 @@
// Initialize states.
for (int i = 0; i < num_threads; ++i) {
new ((ParScanThreadState*)_data + i)
- ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set,
+ ParScanThreadState(&to_space, &young_gen, &old_gen, i, &queue_set,
overflow_stacks, desired_plab_sz, term);
}
}
-inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i)
-{
+inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) {
assert(i >= 0 && i < length(), "sanity check!");
return ((ParScanThreadState*)_data)[i];
}
@@ -357,8 +360,7 @@
}
}
-void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed)
-{
+void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed) {
_term.reset_for_reuse(active_threads);
if (promotion_failed) {
for (int i = 0; i < length(); ++i) {
@@ -368,36 +370,27 @@
}
#if TASKQUEUE_STATS
-void
-ParScanThreadState::reset_stats()
-{
+void ParScanThreadState::reset_stats() {
taskqueue_stats().reset();
_term_attempts = 0;
_overflow_refills = 0;
_overflow_refill_objs = 0;
}
-void ParScanThreadStateSet::reset_stats()
-{
+void ParScanThreadStateSet::reset_stats() {
for (int i = 0; i < length(); ++i) {
thread_state(i).reset_stats();
}
}
-void
-ParScanThreadStateSet::print_termination_stats_hdr(outputStream* const st)
-{
+void ParScanThreadStateSet::print_termination_stats_hdr(outputStream* const st) {
st->print_raw_cr("GC Termination Stats");
- st->print_raw_cr(" elapsed --strong roots-- "
- "-------termination-------");
- st->print_raw_cr("thr ms ms % "
- " ms % attempts");
- st->print_raw_cr("--- --------- --------- ------ "
- "--------- ------ --------");
+ st->print_raw_cr(" elapsed --strong roots-- -------termination-------");
+ st->print_raw_cr("thr ms ms % ms % attempts");
+ st->print_raw_cr("--- --------- --------- ------ --------- ------ --------");
}
-void ParScanThreadStateSet::print_termination_stats(outputStream* const st)
-{
+void ParScanThreadStateSet::print_termination_stats(outputStream* const st) {
print_termination_stats_hdr(st);
for (int i = 0; i < length(); ++i) {
@@ -405,23 +398,20 @@
const double elapsed_ms = pss.elapsed_time() * 1000.0;
const double s_roots_ms = pss.strong_roots_time() * 1000.0;
const double term_ms = pss.term_time() * 1000.0;
- st->print_cr("%3d %9.2f %9.2f %6.2f "
- "%9.2f %6.2f " SIZE_FORMAT_W(8),
+ st->print_cr("%3d %9.2f %9.2f %6.2f %9.2f %6.2f " SIZE_FORMAT_W(8),
i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
term_ms, term_ms * 100 / elapsed_ms, pss.term_attempts());
}
}
// Print stats related to work queue activity.
-void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st)
-{
+void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st) {
st->print_raw_cr("GC Task Stats");
st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr();
st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
}
-void ParScanThreadStateSet::print_taskqueue_stats(outputStream* const st)
-{
+void ParScanThreadStateSet::print_taskqueue_stats(outputStream* const st) {
print_taskqueue_stats_hdr(st);
TaskQueueStats totals;
@@ -443,8 +433,7 @@
}
#endif // TASKQUEUE_STATS
-void ParScanThreadStateSet::flush()
-{
+void ParScanThreadStateSet::flush() {
// Work in this loop should be kept as lightweight as
// possible since this might otherwise become a bottleneck
// to scaling. Should we add heavy-weight work into this
@@ -454,12 +443,12 @@
// Flush stats related to To-space PLAB activity and
// retire the last buffer.
- par_scan_state.to_space_alloc_buffer()->flush_and_retire_stats(_gen.plab_stats());
+ par_scan_state.to_space_alloc_buffer()->flush_and_retire_stats(_young_gen.plab_stats());
// Every thread has its own age table. We need to merge
// them all into one.
ageTable *local_table = par_scan_state.age_table();
- _gen.age_table()->merge(local_table);
+ _young_gen.age_table()->merge(local_table);
// Inform old gen that we're done.
_old_gen.par_promote_alloc_done(i);
@@ -478,8 +467,7 @@
ParScanClosure::ParScanClosure(ParNewGeneration* g,
ParScanThreadState* par_scan_state) :
- OopsInKlassOrGenClosure(g), _par_scan_state(par_scan_state), _g(g)
-{
+ OopsInKlassOrGenClosure(g), _par_scan_state(par_scan_state), _g(g) {
_boundary = _g->reserved().end();
}
@@ -531,24 +519,23 @@
ObjToScanQueue* work_q = par_scan_state()->work_queue();
while (true) {
-
// Scan to-space and old-gen objs until we run out of both.
oop obj_to_scan;
par_scan_state()->trim_queues(0);
// We have no local work, attempt to steal from other threads.
- // attempt to steal work from promoted.
+ // Attempt to steal work from promoted.
if (task_queues()->steal(par_scan_state()->thread_num(),
par_scan_state()->hash_seed(),
obj_to_scan)) {
bool res = work_q->push(obj_to_scan);
assert(res, "Empty queue should have room for a push.");
- // if successful, goto Start.
+ // If successful, goto Start.
continue;
- // try global overflow list.
+ // Try global overflow list.
} else if (par_gen()->take_from_overflow_list(par_scan_state())) {
continue;
}
@@ -564,15 +551,17 @@
par_scan_state()->end_term_time();
}
-ParNewGenTask::ParNewGenTask(ParNewGeneration* young_gen, Generation* old_gen,
- HeapWord* young_old_boundary, ParScanThreadStateSet* state_set,
+ParNewGenTask::ParNewGenTask(ParNewGeneration* young_gen,
+ Generation* old_gen,
+ HeapWord* young_old_boundary,
+ ParScanThreadStateSet* state_set,
StrongRootsScope* strong_roots_scope) :
AbstractGangTask("ParNewGeneration collection"),
_young_gen(young_gen), _old_gen(old_gen),
_young_old_boundary(young_old_boundary),
_state_set(state_set),
_strong_roots_scope(strong_roots_scope)
- {}
+{}
void ParNewGenTask::work(uint worker_id) {
GenCollectedHeap* gch = GenCollectedHeap::heap();
@@ -595,8 +584,7 @@
par_scan_state.start_strong_roots();
gch->gen_process_roots(_strong_roots_scope,
GenCollectedHeap::YoungGen,
- true, // Process younger gens, if any,
- // as strong roots.
+ true, // Process younger gens, if any, as strong roots.
GenCollectedHeap::SO_ScavengeCodeCache,
GenCollectedHeap::StrongAndWeakRoots,
&par_scan_state.to_space_root_closure(),
@@ -613,8 +601,7 @@
#pragma warning( push )
#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
#endif
-ParNewGeneration::
-ParNewGeneration(ReservedSpace rs, size_t initial_byte_size)
+ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size)
: DefNewGeneration(rs, initial_byte_size, "PCopy"),
_overflow_list(NULL),
_is_alive_closure(this),
@@ -625,20 +612,19 @@
_task_queues = new ObjToScanQueueSet(ParallelGCThreads);
guarantee(_task_queues != NULL, "task_queues allocation failure.");
- for (uint i1 = 0; i1 < ParallelGCThreads; i1++) {
+ for (uint i = 0; i < ParallelGCThreads; i++) {
ObjToScanQueue *q = new ObjToScanQueue();
guarantee(q != NULL, "work_queue Allocation failure.");
- _task_queues->register_queue(i1, q);
+ _task_queues->register_queue(i, q);
}
- for (uint i2 = 0; i2 < ParallelGCThreads; i2++)
- _task_queues->queue(i2)->initialize();
+ for (uint i = 0; i < ParallelGCThreads; i++) {
+ _task_queues->queue(i)->initialize();
+ }
_overflow_stacks = NULL;
if (ParGCUseLocalOverflow) {
-
- // typedef to workaround NEW_C_HEAP_ARRAY macro, which can not deal
- // with ','
+ // typedef to workaround NEW_C_HEAP_ARRAY macro, which can not deal with ','
typedef Stack<oop, mtGC> GCOopStack;
_overflow_stacks = NEW_C_HEAP_ARRAY(GCOopStack, ParallelGCThreads, mtGC);
@@ -742,7 +728,7 @@
typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
public:
ParNewRefProcTaskProxy(ProcessTask& task,
- ParNewGeneration& gen,
+ ParNewGeneration& young_gen,
Generation& old_gen,
HeapWord* young_old_boundary,
ParScanThreadStateSet& state_set);
@@ -768,11 +754,9 @@
_old_gen(old_gen),
_young_old_boundary(young_old_boundary),
_state_set(state_set)
-{
-}
+{ }
-void ParNewRefProcTaskProxy::work(uint worker_id)
-{
+void ParNewRefProcTaskProxy::work(uint worker_id) {
ResourceMark rm;
HandleMark hm;
ParScanThreadState& par_scan_state = _state_set.thread_state(worker_id);
@@ -792,15 +776,12 @@
_task(task)
{ }
- virtual void work(uint worker_id)
- {
+ virtual void work(uint worker_id) {
_task.work(worker_id);
}
};
-
-void ParNewRefProcTaskExecutor::execute(ProcessTask& task)
-{
+void ParNewRefProcTaskExecutor::execute(ProcessTask& task) {
GenCollectedHeap* gch = GenCollectedHeap::heap();
WorkGang* workers = gch->workers();
assert(workers != NULL, "Need parallel worker threads.");
@@ -812,8 +793,7 @@
_young_gen.promotion_failed());
}
-void ParNewRefProcTaskExecutor::execute(EnqueueTask& task)
-{
+void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) {
GenCollectedHeap* gch = GenCollectedHeap::heap();
WorkGang* workers = gch->workers();
assert(workers != NULL, "Need parallel worker threads.");
@@ -821,8 +801,7 @@
workers->run_task(&enq_task);
}
-void ParNewRefProcTaskExecutor::set_single_threaded_mode()
-{
+void ParNewRefProcTaskExecutor::set_single_threaded_mode() {
_state_set.flush();
GenCollectedHeap* gch = GenCollectedHeap::heap();
gch->save_marks();
@@ -830,7 +809,8 @@
ScanClosureWithParBarrier::
ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier) :
- ScanClosure(g, gc_barrier) {}
+ ScanClosure(g, gc_barrier)
+{ }
EvacuateFollowersClosureGeneral::
EvacuateFollowersClosureGeneral(GenCollectedHeap* gch,
@@ -838,7 +818,7 @@
OopsInGenClosure* older) :
_gch(gch),
_scan_cur_or_nonheap(cur), _scan_older(older)
-{}
+{ }
void EvacuateFollowersClosureGeneral::do_void() {
do {
@@ -850,7 +830,6 @@
} while (!_gch->no_allocs_since_save_marks());
}
-
// A Generation that does parallel young-gen collection.
void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set) {
@@ -996,9 +975,9 @@
if (ZapUnusedHeapArea) {
// This is now done here because of the piece-meal mangling which
// can check for valid mangling at intermediate points in the
- // collection(s). When a minor collection fails to collect
+ // collection(s). When a young collection fails to collect
// sufficient space resizing of the young generation can occur
- // an redistribute the spaces in the young generation. Mangle
+ // and redistribute the spaces in the young generation. Mangle
// here so that unzapped regions don't get distributed to
// other spaces.
to()->mangle_unused_area();
@@ -1113,8 +1092,10 @@
// thus avoiding the need to undo the copy as in
// copy_to_survivor_space_avoiding_with_undo.
-oop ParNewGeneration::copy_to_survivor_space(
- ParScanThreadState* par_scan_state, oop old, size_t sz, markOop m) {
+oop ParNewGeneration::copy_to_survivor_space(ParScanThreadState* par_scan_state,
+ oop old,
+ size_t sz,
+ markOop m) {
// In the sequential version, this assert also says that the object is
// not forwarded. That might not be the case here. It is the case that
// the caller observed it to be not forwarded at some time in the past.
@@ -1141,8 +1122,7 @@
}
if (new_obj == NULL) {
- // Either to-space is full or we decided to promote
- // try allocating obj tenured
+ // Either to-space is full or we decided to promote try allocating obj tenured
// Attempt to install a null forwarding pointer (atomically),
// to claim the right to install the real forwarding pointer.
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -71,11 +71,7 @@
ParScanWithoutBarrierClosure _to_space_closure; // scan_without_gc_barrier
ParScanWithBarrierClosure _old_gen_closure; // scan_with_gc_barrier
ParRootScanWithoutBarrierClosure _to_space_root_closure; // scan_root_without_gc_barrier
- // One of these two will be passed to process_roots, which will
- // set its generation. The first is for two-gen configs where the
- // old gen collects the perm gen; the second is for arbitrary configs.
- // The second isn't used right now (it used to be used for the train, an
- // incremental collector) but the declaration has been left as a reminder.
+ // Will be passed to process_roots to set its generation.
ParRootScanWithBarrierTwoGensClosure _older_gen_closure;
// This closure will always be bound to the old gen; it will be used
// in evacuate_followers.
@@ -85,7 +81,6 @@
ParScanWeakRefClosure _scan_weak_ref_closure;
ParKeepAliveClosure _keep_alive_closure;
-
Space* _to_space;
Space* to_space() { return _to_space; }
--- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1143,7 +1143,7 @@
while (curr < end) {
Prefetch::read(curr, interval);
oop obj = oop(curr);
- int size = obj->oop_iterate(&cl);
+ int size = obj->oop_iterate_size(&cl);
assert(size == obj->size(), "sanity");
curr += size;
}
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -367,7 +367,7 @@
_max = _bottom + HeapRegion::min_region_size_in_words();
// Tell mark-sweep that objects in this region are not to be marked.
- G1MarkSweep::mark_range_archive(MemRegion(_bottom, HeapRegion::GrainWords));
+ G1MarkSweep::set_range_archive(MemRegion(_bottom, HeapRegion::GrainWords), true);
// Since we've modified the old set, call update_sizes.
_g1h->g1mm()->update_sizes();
--- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -27,6 +27,7 @@
#include "gc/g1/g1BlockOffsetTable.hpp"
#include "gc/g1/heapRegion.hpp"
+#include "gc/shared/memset_with_concurrent_readers.hpp"
#include "gc/shared/space.hpp"
inline HeapWord* G1BlockOffsetTable::block_start(const void* addr) {
@@ -68,15 +69,7 @@
check_index(right, "right index out of range");
assert(left <= right, "indexes out of order");
size_t num_cards = right - left + 1;
- if (UseMemSetInBOT) {
- memset(&_offset_array[left], offset, num_cards);
- } else {
- size_t i = left;
- const size_t end = i + num_cards;
- for (; i < end; i++) {
- _offset_array[i] = offset;
- }
- }
+ memset_with_concurrent_readers(&_offset_array[left], offset, num_cards);
}
// Variant of index_for that does not check the index for validity.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "code/nmethod.hpp"
+#include "gc/g1/g1CodeBlobClosure.hpp"
+#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "gc/g1/heapRegionRemSet.hpp"
+#include "oops/oop.inline.hpp"
+
+template <typename T>
+void G1CodeBlobClosure::HeapRegionGatheringOopClosure::do_oop_work(T* p) {
+ _work->do_oop(p);
+ T oop_or_narrowoop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(oop_or_narrowoop)) {
+ oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop);
+ HeapRegion* hr = _g1h->heap_region_containing_raw(o);
+ assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in collection set then evacuation failed and nm must already be in the remset");
+ hr->add_strong_code_root(_nm);
+ }
+}
+
+void G1CodeBlobClosure::HeapRegionGatheringOopClosure::do_oop(oop* o) {
+ do_oop_work(o);
+}
+
+void G1CodeBlobClosure::HeapRegionGatheringOopClosure::do_oop(narrowOop* o) {
+ do_oop_work(o);
+}
+
+void G1CodeBlobClosure::do_code_blob(CodeBlob* cb) {
+ nmethod* nm = cb->as_nmethod_or_null();
+ if (nm != NULL) {
+ if (!nm->test_set_oops_do_mark()) {
+ _oc.set_nm(nm);
+ nm->oops_do(&_oc);
+ nm->fix_oop_relocations();
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1CodeBlobClosure.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "gc/g1/g1CollectedHeap.hpp"
+#include "memory/iterator.hpp"
+
+class nmethod;
+
+class G1CodeBlobClosure : public CodeBlobClosure {
+ class HeapRegionGatheringOopClosure : public OopClosure {
+ G1CollectedHeap* _g1h;
+ OopClosure* _work;
+ nmethod* _nm;
+
+ template <typename T>
+ void do_oop_work(T* p);
+
+ public:
+ HeapRegionGatheringOopClosure(OopClosure* oc) : _g1h(G1CollectedHeap::heap()), _work(oc), _nm(NULL) {}
+
+ void do_oop(oop* o);
+ void do_oop(narrowOop* o);
+
+ void set_nm(nmethod* nm) {
+ _nm = nm;
+ }
+ };
+
+ HeapRegionGatheringOopClosure _oc;
+public:
+ G1CodeBlobClosure(OopClosure* oc) : _oc(oc) {}
+
+ void do_code_blob(CodeBlob* cb);
+};
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -65,6 +65,7 @@
#include "memory/iterator.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.inline.hpp"
+#include "runtime/init.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/vmThread.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -949,6 +950,7 @@
}
bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges, size_t count) {
+ assert(!is_init_completed(), "Expect to be called at JVM init time");
assert(ranges != NULL, "MemRegion array NULL");
assert(count != 0, "No MemRegions provided");
MutexLockerEx x(Heap_lock);
@@ -1037,12 +1039,13 @@
}
// Notify mark-sweep of the archive range.
- G1MarkSweep::mark_range_archive(curr_range);
+ G1MarkSweep::set_range_archive(curr_range, true);
}
return true;
}
void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) {
+ assert(!is_init_completed(), "Expect to be called at JVM init time");
assert(ranges != NULL, "MemRegion array NULL");
assert(count != 0, "No MemRegions provided");
MemRegion reserved = _hrm.reserved();
@@ -1125,6 +1128,81 @@
return result;
}
+void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
+ assert(!is_init_completed(), "Expect to be called at JVM init time");
+ assert(ranges != NULL, "MemRegion array NULL");
+ assert(count != 0, "No MemRegions provided");
+ MemRegion reserved = _hrm.reserved();
+ HeapWord* prev_last_addr = NULL;
+ HeapRegion* prev_last_region = NULL;
+ size_t size_used = 0;
+ size_t uncommitted_regions = 0;
+
+ // For each Memregion, free the G1 regions that constitute it, and
+ // notify mark-sweep that the range is no longer to be considered 'archive.'
+ MutexLockerEx x(Heap_lock);
+ for (size_t i = 0; i < count; i++) {
+ HeapWord* start_address = ranges[i].start();
+ HeapWord* last_address = ranges[i].last();
+
+ assert(reserved.contains(start_address) && reserved.contains(last_address),
+ err_msg("MemRegion outside of heap [" PTR_FORMAT ", " PTR_FORMAT "]",
+ p2i(start_address), p2i(last_address)));
+ assert(start_address > prev_last_addr,
+ err_msg("Ranges not in ascending order: " PTR_FORMAT " <= " PTR_FORMAT ,
+ p2i(start_address), p2i(prev_last_addr)));
+ size_used += ranges[i].byte_size();
+ prev_last_addr = last_address;
+
+ HeapRegion* start_region = _hrm.addr_to_region(start_address);
+ HeapRegion* last_region = _hrm.addr_to_region(last_address);
+
+ // Check for ranges that start in the same G1 region in which the previous
+ // range ended, and adjust the start address so we don't try to free
+ // the same region again. If the current range is entirely within that
+ // region, skip it.
+ if (start_region == prev_last_region) {
+ start_address = start_region->end();
+ if (start_address > last_address) {
+ continue;
+ }
+ start_region = _hrm.addr_to_region(start_address);
+ }
+ prev_last_region = last_region;
+
+ // After verifying that each region was marked as an archive region by
+ // alloc_archive_regions, set it free and empty and uncommit it.
+ HeapRegion* curr_region = start_region;
+ while (curr_region != NULL) {
+ guarantee(curr_region->is_archive(),
+ err_msg("Expected archive region at index %u", curr_region->hrm_index()));
+ uint curr_index = curr_region->hrm_index();
+ _old_set.remove(curr_region);
+ curr_region->set_free();
+ curr_region->set_top(curr_region->bottom());
+ if (curr_region != last_region) {
+ curr_region = _hrm.next_region_in_heap(curr_region);
+ } else {
+ curr_region = NULL;
+ }
+ _hrm.shrink_at(curr_index, 1);
+ uncommitted_regions++;
+ }
+
+ // Notify mark-sweep that this is no longer an archive range.
+ G1MarkSweep::set_range_archive(ranges[i], false);
+ }
+
+ if (uncommitted_regions != 0) {
+ ergo_verbose1(ErgoHeapSizing,
+ "attempt heap shrinking",
+ ergo_format_reason("uncommitted archive regions")
+ ergo_format_byte("total size"),
+ HeapRegion::GrainWords * HeapWordSize * uncommitted_regions);
+ }
+ decrease_used(size_used);
+}
+
HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
uint* gc_count_before_ret,
uint* gclocker_retry_count_ret) {
@@ -2845,9 +2923,9 @@
}
// For G1 TLABs should not contain humongous objects, so the maximum TLAB size
-// must be smaller than the humongous object limit.
+// must be equal to the humongous object limit.
size_t G1CollectedHeap::max_tlab_size() const {
- return align_size_down(_humongous_object_threshold_in_words - 1, MinObjAlignment);
+ return align_size_down(_humongous_object_threshold_in_words, MinObjAlignment);
}
size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const {
@@ -4051,7 +4129,9 @@
g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty);
#endif // YOUNG_LIST_VERBOSE
- g1_policy()->finalize_cset(target_pause_time_ms, evacuation_info);
+ g1_policy()->finalize_cset(target_pause_time_ms);
+
+ evacuation_info.set_collectionset_regions(g1_policy()->cset_region_length());
register_humongous_regions_with_cset();
@@ -4175,7 +4255,10 @@
// investigate this in CR 7178365.
double sample_end_time_sec = os::elapsedTime();
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
- g1_policy()->record_collection_pause_end(pause_time_ms, evacuation_info);
+ g1_policy()->record_collection_pause_end(pause_time_ms);
+
+ evacuation_info.set_collectionset_used_before(g1_policy()->collection_set_bytes_used_before());
+ evacuation_info.set_bytes_copied(g1_policy()->bytes_copied_during_gc());
MemoryService::track_memory_usage();
@@ -4501,8 +4584,7 @@
bool only_young, bool claim)
: _oop_closure(oop_closure),
_oop_in_klass_closure(oop_closure->g1(),
- oop_closure->pss(),
- oop_closure->rp()),
+ oop_closure->pss()),
_klass_in_cld_closure(&_oop_in_klass_closure, only_young),
_claim(claim) {
@@ -4531,18 +4613,18 @@
bool only_young = _g1h->collector_state()->gcs_are_young();
// Non-IM young GC.
- G1ParCopyClosure<G1BarrierNone, G1MarkNone> scan_only_root_cl(_g1h, pss, rp);
+ G1ParCopyClosure<G1BarrierNone, G1MarkNone> scan_only_root_cl(_g1h, pss);
G1CLDClosure<G1MarkNone> scan_only_cld_cl(&scan_only_root_cl,
only_young, // Only process dirty klasses.
false); // No need to claim CLDs.
// IM young GC.
// Strong roots closures.
- G1ParCopyClosure<G1BarrierNone, G1MarkFromRoot> scan_mark_root_cl(_g1h, pss, rp);
+ G1ParCopyClosure<G1BarrierNone, G1MarkFromRoot> scan_mark_root_cl(_g1h, pss);
G1CLDClosure<G1MarkFromRoot> scan_mark_cld_cl(&scan_mark_root_cl,
false, // Process all klasses.
true); // Need to claim CLDs.
// Weak roots closures.
- G1ParCopyClosure<G1BarrierNone, G1MarkPromotedFromRoot> scan_mark_weak_root_cl(_g1h, pss, rp);
+ G1ParCopyClosure<G1BarrierNone, G1MarkPromotedFromRoot> scan_mark_weak_root_cl(_g1h, pss);
G1CLDClosure<G1MarkPromotedFromRoot> scan_mark_weak_cld_cl(&scan_mark_weak_root_cl,
false, // Process all klasses.
true); // Need to claim CLDs.
@@ -4582,9 +4664,9 @@
worker_id);
G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, pss);
- _root_processor->scan_remembered_sets(&push_heap_rs_cl,
- weak_root_cl,
- worker_id);
+ _g1h->g1_rem_set()->oops_into_collection_set_do(&push_heap_rs_cl,
+ weak_root_cl,
+ worker_id);
double strong_roots_sec = os::elapsedTime() - start_strong_roots_sec;
double term_sec = 0.0;
@@ -5241,9 +5323,9 @@
G1ParScanThreadState* pss = _pss[worker_id];
pss->set_ref_processor(NULL);
- G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss, NULL);
-
- G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, pss, NULL);
+ G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss);
+
+ G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, pss);
OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl;
@@ -5341,9 +5423,9 @@
pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "both queue and overflow should be empty");
- G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss, NULL);
-
- G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, pss, NULL);
+ G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss);
+
+ G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, pss);
OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl;
@@ -5451,9 +5533,9 @@
// closures while we're actually processing the discovered
// reference objects.
- G1ParScanExtRootClosure only_copy_non_heap_cl(this, pss, NULL);
-
- G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(this, pss, NULL);
+ G1ParScanExtRootClosure only_copy_non_heap_cl(this, pss);
+
+ G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(this, pss);
OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl;
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -757,6 +757,12 @@
// alloc_archive_regions, and after class loading has occurred.
void fill_archive_regions(MemRegion* range, size_t count);
+ // For each of the specified MemRegions, uncommit the containing G1 regions
+ // which had been allocated by alloc_archive_regions. This should be called
+ // rather than fill_archive_regions at JVM init time if the archive file
+ // mapping failed, with the same non-overlapping and sorted MemRegion array.
+ void dealloc_archive_regions(MemRegion* range, size_t count);
+
protected:
// Shrink the garbage-first heap by at most the given size (in bytes!).
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -181,15 +181,6 @@
G1ErgoVerbose::set_enabled(false);
}
- // Verify PLAB sizes
- const size_t region_size = HeapRegion::GrainWords;
- if (YoungPLABSize > region_size || OldPLABSize > region_size) {
- char buffer[128];
- jio_snprintf(buffer, sizeof(buffer), "%sPLABSize should be at most " SIZE_FORMAT,
- OldPLABSize > region_size ? "Old" : "Young", region_size);
- vm_exit_during_initialization(buffer);
- }
-
_recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
_prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
@@ -932,7 +923,7 @@
// Anything below that is considered to be zero
#define MIN_TIMER_GRANULARITY 0.0000001
-void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, EvacuationInfo& evacuation_info) {
+void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) {
double end_time_sec = os::elapsedTime();
assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(),
"otherwise, the subtraction below does not make sense");
@@ -964,9 +955,6 @@
_mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0,
end_time_sec, _g1->gc_tracer_stw()->gc_id());
- evacuation_info.set_collectionset_used_before(_collection_set_bytes_used_before);
- evacuation_info.set_bytes_copied(_bytes_copied_during_gc);
-
if (update_stats) {
_trace_young_gen_time_data.record_end_collection(pause_time_ms, phase_times());
// this is where we update the allocation rate of the application
@@ -1883,7 +1871,7 @@
}
-void G1CollectorPolicy::finalize_cset(double target_pause_time_ms, EvacuationInfo& evacuation_info) {
+void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
double young_start_time_sec = os::elapsedTime();
YoungList* young_list = _g1->young_list();
@@ -2093,7 +2081,6 @@
double non_young_end_time_sec = os::elapsedTime();
phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0);
- evacuation_info.set_collectionset_regions(cset_region_length());
}
void TraceYoungGenTimeData::record_start_collection(double time_to_stop_the_world_ms) {
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -604,10 +604,6 @@
virtual G1CollectorPolicy* as_g1_policy() { return this; }
- virtual CollectorPolicy::Name kind() {
- return CollectorPolicy::G1CollectorPolicyKind;
- }
-
G1CollectorState* collector_state();
G1GCPhaseTimes* phase_times() const { return _phase_times; }
@@ -634,13 +630,11 @@
virtual HeapWord* satisfy_failed_allocation(size_t size,
bool is_tlab);
- BarrierSet::Name barrier_set_name() { return BarrierSet::G1SATBCTLogging; }
-
bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0);
// Record the start and end of an evacuation pause.
void record_collection_pause_start(double start_time_sec);
- void record_collection_pause_end(double pause_time_ms, EvacuationInfo& evacuation_info);
+ void record_collection_pause_end(double pause_time_ms);
// Record the start and end of a full collection.
void record_full_collection_start();
@@ -682,6 +676,10 @@
return _bytes_copied_during_gc;
}
+ size_t collection_set_bytes_used_before() const {
+ return _collection_set_bytes_used_before;
+ }
+
// Determine whether there are candidate regions so that the
// next GC should be mixed. The two action strings are used
// in the ergo output when the method returns true or false.
@@ -691,7 +689,7 @@
// Choose a new collection set. Marks the chosen regions as being
// "in_collection_set", and links them together. The head and number of
// the collection set are available via access methods.
- void finalize_cset(double target_pause_time_ms, EvacuationInfo& evacuation_info);
+ void finalize_cset(double target_pause_time_ms);
// The head of the list (via "next_in_collection_set()") representing the
// current collection set.
--- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -54,17 +54,46 @@
_allocated, _wasted, _region_end_waste, _unused, used()));
_allocated = 1;
}
- // We account region end waste fully to PLAB allocation. This is not completely fair,
- // but is a conservative assumption because PLABs may be sized flexibly while we
- // cannot adjust direct allocations.
- // In some cases, wasted_frac may become > 1 but that just reflects the problem
- // with region_end_waste.
- double wasted_frac = (double)(_unused + _wasted + _region_end_waste) / (double)_allocated;
- size_t target_refills = (size_t)((wasted_frac * TargetSurvivorRatio) / TargetPLABWastePct);
- if (target_refills == 0) {
- target_refills = 1;
- }
- size_t cur_plab_sz = used() / target_refills;
+ // The size of the PLAB caps the amount of space that can be wasted at the
+ // end of the collection. In the worst case the last PLAB could be completely
+ // empty.
+ // This allows us to calculate the new PLAB size to achieve the
+ // TargetPLABWastePct given the latest memory usage and that the last buffer
+ // will be G1LastPLABAverageOccupancy full.
+ //
+ // E.g. assume that if in the current GC 100 words were allocated and a
+ // TargetPLABWastePct of 10 had been set.
+ //
+ // So we could waste up to 10 words to meet that percentage. Given that we
+ // also assume that that buffer is typically half-full, the new desired PLAB
+ // size is set to 20 words.
+ //
+ // The amount of allocation performed should be independent of the number of
+ // threads, so should the maximum waste we can spend in total. So if
+ // we used n threads to allocate, each of them can spend maximum waste/n words in
+ // a first rough approximation. The number of threads only comes into play later
+ // when actually retrieving the actual desired PLAB size.
+ //
+ // After calculating this optimal PLAB size the algorithm applies the usual
+ // exponential decaying average over this value to guess the next PLAB size.
+ //
+ // We account region end waste fully to PLAB allocation (in the calculation of
+ // what we consider as "used_for_waste_calculation" below). This is not
+ // completely fair, but is a conservative assumption because PLABs may be sized
+ // flexibly while we cannot adjust inline allocations.
+ // Allocation during GC will try to minimize region end waste so this impact
+ // should be minimal.
+ //
+ // We need to cover overflow when calculating the amount of space actually used
+ // by objects in PLABs when subtracting the region end waste.
+ // Region end waste may be higher than actual allocation. This may occur if many
+ // threads do not allocate anything but a few rather large objects. In this
+ // degenerate case the PLAB size would simply quickly tend to minimum PLAB size,
+ // which is an okay reaction.
+ size_t const used_for_waste_calculation = used() > _region_end_waste ? used() - _region_end_waste : 0;
+
+ size_t const total_waste_allowed = used_for_waste_calculation * TargetPLABWastePct;
+ size_t const cur_plab_sz = (double)total_waste_allowed / G1LastPLABAverageOccupancy;
// Take historical weighted average
_filter.sample(cur_plab_sz);
// Clip from above and below, and align to object boundary
--- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -74,7 +74,7 @@
assert(rp != NULL, "should be non-NULL");
assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Precondition");
- GenMarkSweep::_ref_processor = rp;
+ GenMarkSweep::set_ref_processor(rp);
rp->setup_policy(clear_all_softrefs);
// When collecting the permanent generation Method*s may be moving,
@@ -108,7 +108,7 @@
JvmtiExport::gc_epilogue();
// refs processing: clean slate
- GenMarkSweep::_ref_processor = NULL;
+ GenMarkSweep::set_ref_processor(NULL);
}
@@ -310,9 +310,9 @@
HeapRegion::GrainBytes);
}
-void G1MarkSweep::mark_range_archive(MemRegion range) {
+void G1MarkSweep::set_range_archive(MemRegion range, bool is_archive) {
assert(_archive_check_enabled, "archive range check not enabled");
- _archive_region_map.set_by_address(range, true);
+ _archive_region_map.set_by_address(range, is_archive);
}
bool G1MarkSweep::in_archive_range(oop object) {
--- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -58,8 +58,8 @@
// Create the _archive_region_map which is used to identify archive objects.
static void enable_archive_object_check();
- // Mark the regions containing the specified address range as archive regions.
- static void mark_range_archive(MemRegion range);
+ // Set the regions containing the specified address range as archive/non-archive.
+ static void set_range_archive(MemRegion range, bool is_archive);
// Check if an object is in an archive region using the _archive_region_map.
static bool in_archive_range(oop object);
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -125,8 +125,7 @@
template <class T> void do_oop_work(T* p);
public:
- G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state,
- ReferenceProcessor* rp) :
+ G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
G1ParCopyHelper(g1, par_scan_state) {
assert(_ref_processor == NULL, "sanity");
}
@@ -141,7 +140,6 @@
G1CollectedHeap* g1() { return _g1; };
G1ParScanThreadState* pss() { return _par_scan_state; }
- ReferenceProcessor* rp() { return _ref_processor; };
};
typedef G1ParCopyClosure<G1BarrierNone, G1MarkNone> G1ParScanExtRootClosure;
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -186,6 +186,21 @@
return dest(state);
}
+void G1ParScanThreadState::report_promotion_event(InCSetState const dest_state,
+ oop const old, size_t word_sz, uint age,
+ HeapWord * const obj_ptr,
+ const AllocationContext_t context) const {
+ G1PLAB* alloc_buf = _plab_allocator->alloc_buffer(dest_state, context);
+ if (alloc_buf->contains(obj_ptr)) {
+ _g1h->_gc_tracer_stw->report_promotion_in_new_plab_event(old->klass(), word_sz, age,
+ dest_state.value() == InCSetState::Old,
+ alloc_buf->word_sz());
+ } else {
+ _g1h->_gc_tracer_stw->report_promotion_outside_plab_event(old->klass(), word_sz, age,
+ dest_state.value() == InCSetState::Old);
+ }
+}
+
oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
oop const old,
markOop const old_mark) {
@@ -219,6 +234,10 @@
return handle_evacuation_failure_par(old, old_mark);
}
}
+ if (_g1h->_gc_tracer_stw->should_report_promotion_events()) {
+ // The events are checked individually as part of the actual commit
+ report_promotion_event(dest_state, old, word_sz, age, obj_ptr, context);
+ }
}
assert(obj_ptr != NULL, "when we get here, allocation should have succeeded");
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -173,6 +173,10 @@
bool previous_plab_refill_failed);
inline InCSetState next_state(InCSetState const state, markOop const m, uint& age);
+
+ void report_promotion_event(InCSetState const dest_state,
+ oop const old, size_t word_sz, uint age,
+ HeapWord * const obj_ptr, const AllocationContext_t context) const;
public:
oop copy_to_survivor_space(InCSetState const state, oop const obj, markOop const old_mark);
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -26,6 +26,7 @@
#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/concurrentG1RefineThread.hpp"
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
+#include "gc/g1/g1CodeBlobClosure.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
@@ -228,12 +229,15 @@
};
void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
- CodeBlobClosure* code_root_cl,
+ OopClosure* non_heap_roots,
uint worker_i) {
double rs_time_start = os::elapsedTime();
+
+ G1CodeBlobClosure code_root_cl(non_heap_roots);
+
HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
- ScanRSClosure scanRScl(oc, code_root_cl, worker_i);
+ ScanRSClosure scanRScl(oc, &code_root_cl, worker_i);
_g1->collection_set_iterate_from(startRegion, &scanRScl);
scanRScl.set_try_claimed();
@@ -295,7 +299,7 @@
}
void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
- CodeBlobClosure* code_root_cl,
+ OopClosure* non_heap_roots,
uint worker_i) {
#if CARD_REPEAT_HISTO
ct_freq_update_histo_and_reset();
@@ -318,7 +322,7 @@
DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
updateRS(&into_cset_dcq, worker_i);
- scanRS(oc, code_root_cl, worker_i);
+ scanRS(oc, non_heap_roots, worker_i);
// We now clear the cached values of _cset_rs_update_cl for this worker
_cset_rs_update_cl[worker_i] = NULL;
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -85,7 +85,7 @@
// invoked "blk->set_region" to set the "from" region correctly
// beforehand.)
//
- // Invoke code_root_cl->do_code_blob on the unmarked nmethods
+ // Apply non_heap_roots on the oops of the unmarked nmethods
// on the strong code roots list for each region in the
// collection set.
//
@@ -95,7 +95,7 @@
// the "i" passed to the calling thread's work(i) function.
// In the sequential case this param will be ignored.
void oops_into_collection_set_do(G1ParPushHeapRSClosure* blk,
- CodeBlobClosure* code_root_cl,
+ OopClosure* non_heap_roots,
uint worker_i);
// Prepare for and cleanup after an oops_into_collection_set_do
@@ -107,7 +107,7 @@
void cleanup_after_oops_into_collection_set_do();
void scanRS(G1ParPushHeapRSClosure* oc,
- CodeBlobClosure* code_root_cl,
+ OopClosure* non_heap_roots,
uint worker_i);
void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i);
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -28,6 +28,7 @@
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc/g1/bufferingOopClosure.hpp"
+#include "gc/g1/g1CodeBlobClosure.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1CollectorState.hpp"
@@ -40,57 +41,6 @@
#include "runtime/mutex.hpp"
#include "services/management.hpp"
-class G1CodeBlobClosure : public CodeBlobClosure {
- class HeapRegionGatheringOopClosure : public OopClosure {
- G1CollectedHeap* _g1h;
- OopClosure* _work;
- nmethod* _nm;
-
- template <typename T>
- void do_oop_work(T* p) {
- _work->do_oop(p);
- T oop_or_narrowoop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(oop_or_narrowoop)) {
- oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop);
- HeapRegion* hr = _g1h->heap_region_containing_raw(o);
- assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in CS then evacuation failed and nm must already be in the remset");
- hr->add_strong_code_root(_nm);
- }
- }
-
- public:
- HeapRegionGatheringOopClosure(OopClosure* oc) : _g1h(G1CollectedHeap::heap()), _work(oc), _nm(NULL) {}
-
- void do_oop(oop* o) {
- do_oop_work(o);
- }
-
- void do_oop(narrowOop* o) {
- do_oop_work(o);
- }
-
- void set_nm(nmethod* nm) {
- _nm = nm;
- }
- };
-
- HeapRegionGatheringOopClosure _oc;
-public:
- G1CodeBlobClosure(OopClosure* oc) : _oc(oc) {}
-
- void do_code_blob(CodeBlob* cb) {
- nmethod* nm = cb->as_nmethod_or_null();
- if (nm != NULL) {
- if (!nm->test_set_oops_do_mark()) {
- _oc.set_nm(nm);
- nm->oops_do(&_oc);
- nm->fix_oop_relocations();
- }
- }
- }
-};
-
-
void G1RootProcessor::worker_has_discovered_all_strong_classes() {
assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
@@ -321,14 +271,6 @@
}
}
-void G1RootProcessor::scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs,
- OopClosure* scan_non_heap_weak_roots,
- uint worker_i) {
- G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots);
-
- _g1h->g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
-}
-
uint G1RootProcessor::n_workers() const {
return _srs.n_threads();
}
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -107,13 +107,6 @@
CLDClosure* clds,
CodeBlobClosure* blobs);
- // Apply scan_rs to all locations in the union of the remembered sets for all
- // regions in the collection set
- // (having done "set_region" to indicate the region in which the root resides),
- void scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs,
- OopClosure* scan_non_heap_weak_roots,
- uint worker_i);
-
// Number of worker threads used by the root processor.
uint n_workers() const;
};
--- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -27,6 +27,7 @@
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/g1/satbQueue.hpp"
+#include "gc/shared/memset_with_concurrent_readers.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/mutexLocker.hpp"
@@ -108,15 +109,7 @@
jbyte *const first = byte_for(mr.start());
jbyte *const last = byte_after(mr.last());
- // Below we may use an explicit loop instead of memset() because on
- // certain platforms memset() can give concurrent readers phantom zeros.
- if (UseMemSetInBOT) {
- memset(first, g1_young_gen, last - first);
- } else {
- for (jbyte* i = first; i < last; i++) {
- *i = g1_young_gen;
- }
- }
+ memset_with_concurrent_readers(first, g1_young_gen, last - first);
}
#ifndef PRODUCT
@@ -207,7 +200,7 @@
// Otherwise, log it.
G1SATBCardTableLoggingModRefBS* g1_bs =
barrier_set_cast<G1SATBCardTableLoggingModRefBS>(G1CollectedHeap::heap()->barrier_set());
- g1_bs->write_ref_field_work(field, new_val);
+ g1_bs->write_ref_field_work(field, new_val, false);
}
void
--- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -147,6 +147,10 @@
private:
G1SATBCardTableLoggingModRefBSChangedListener _listener;
DirtyCardQueueSet& _dcqs;
+
+ protected:
+ virtual void write_ref_field_work(void* field, oop new_val, bool release);
+
public:
static size_t compute_size(size_t mem_region_size_in_words) {
size_t number_of_slots = (mem_region_size_in_words / card_size_in_words);
@@ -165,8 +169,6 @@
virtual void resize_covered_region(MemRegion new_region) { ShouldNotReachHere(); }
- void write_ref_field_work(void* field, oop new_val, bool release = false);
-
// Can be called from static contexts.
static void write_ref_field_static(void* field, oop new_val);
--- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -82,6 +82,11 @@
"If true, enable reference discovery during concurrent " \
"marking and reference processing at the end of remark.") \
\
+ experimental(double, G1LastPLABAverageOccupancy, 50.0, \
+ "The expected average occupancy of the last PLAB in " \
+ "percent.") \
+ range(0.001, 100.0) \
+ \
product(size_t, G1SATBBufferSize, 1*K, \
"Number of entries in an SATB log buffer.") \
\
--- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -68,7 +68,7 @@
// or it was allocated after marking finished, then we add it. Otherwise
// we can safely ignore the object.
if (!g1h->is_obj_dead(oop(cur), _hr)) {
- oop_size = oop(cur)->oop_iterate(_rs_scan, mr);
+ oop_size = oop(cur)->oop_iterate_size(_rs_scan, mr);
} else {
oop_size = _hr->block_size(cur);
}
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -426,7 +426,7 @@
(num_last_found = find_empty_from_idx_reverse(cur, &idx_last_found)) > 0) {
uint to_remove = MIN2(num_regions_to_remove - removed, num_last_found);
- uncommit_regions(idx_last_found + num_last_found - to_remove, to_remove);
+ shrink_at(idx_last_found + num_last_found - to_remove, to_remove);
cur = idx_last_found;
removed += to_remove;
@@ -437,6 +437,17 @@
return removed;
}
+void HeapRegionManager::shrink_at(uint index, size_t num_regions) {
+#ifdef ASSERT
+ for (uint i = index; i < (index + num_regions); i++) {
+ assert(is_available(i), err_msg("Expected available region at index %u", i));
+ assert(at(i)->is_empty(), err_msg("Expected empty region at index %u", i));
+ assert(at(i)->is_free(), err_msg("Expected free region at index %u", i));
+ }
+#endif
+ uncommit_regions(index, num_regions);
+}
+
uint HeapRegionManager::find_empty_from_idx_reverse(uint start_idx, uint* res_idx) const {
guarantee(start_idx < _allocated_heapregions_length, "checking");
guarantee(res_idx != NULL, "checking");
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -241,6 +241,10 @@
// Return the actual number of uncommitted regions.
uint shrink_by(uint num_regions_to_remove);
+ // Uncommit a number of regions starting at the specified index, which must be available,
+ // empty, and free.
+ void shrink_at(uint index, size_t num_regions);
+
void verify();
// Do some sanity checking.
--- a/hotspot/src/share/vm/gc/g1/heapRegionType.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionType.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -35,7 +35,7 @@
// We encode the value of the heap region type so the generation can be
// determined quickly. The tag is split into two parts:
//
- // major type (young, humongous) : top N-1 bits
+ // major type (young, old, humongous, archive) : top N-1 bits
// minor type (eden / survivor, starts / cont hum, etc.) : bottom 1 bit
//
// If there's need to increase the number of minor types in the
--- a/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -89,7 +89,7 @@
CheckForUnmarkedOops object_check(_young_gen, _card_table);
obj->oop_iterate_no_header(&object_check);
if (object_check.has_unmarked_oop()) {
- assert(_card_table->addr_is_marked_imprecise(obj), "Found unmarked young_gen object");
+ guarantee(_card_table->addr_is_marked_imprecise(obj), "Found unmarked young_gen object");
}
}
};
--- a/hotspot/src/share/vm/gc/parallel/cardTableExtension.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/cardTableExtension.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -56,13 +56,7 @@
CardTableExtension(MemRegion whole_heap) :
CardTableModRefBS(
whole_heap,
- // Concrete tag should be BarrierSet::CardTableExtension.
- // That will presently break things in a bunch of places though.
- // The concrete tag is used as a dispatch key in many places, and
- // CardTableExtension does not correctly dispatch in some of those
- // uses. This will be addressed as part of a reorganization of the
- // BarrierSet hierarchy.
- BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableExtension))
+ BarrierSet::FakeRtti(BarrierSet::CardTableExtension))
{ }
// Scavenge support
--- a/hotspot/src/share/vm/gc/parallel/immutableSpace.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/immutableSpace.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -44,7 +44,7 @@
HeapWord* t = end();
// Could call objects iterate, but this is easier.
while (obj_addr < t) {
- obj_addr += oop(obj_addr)->oop_iterate(cl);
+ obj_addr += oop(obj_addr)->oop_iterate_size(cl);
}
}
--- a/hotspot/src/share/vm/gc/parallel/mutableSpace.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/mutableSpace.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -213,15 +213,6 @@
return (HeapWord*)Atomic::cmpxchg_ptr(obj, top_addr(), expected_top) == expected_top;
}
-void MutableSpace::oop_iterate(ExtendedOopClosure* cl) {
- HeapWord* obj_addr = bottom();
- HeapWord* t = top();
- // Could call objects iterate, but this is easier.
- while (obj_addr < t) {
- obj_addr += oop(obj_addr)->oop_iterate(cl);
- }
-}
-
void MutableSpace::oop_iterate_no_header(OopClosure* cl) {
HeapWord* obj_addr = bottom();
HeapWord* t = top();
--- a/hotspot/src/share/vm/gc/parallel/mutableSpace.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/mutableSpace.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -134,7 +134,6 @@
bool cas_deallocate(HeapWord *obj, size_t size);
// Iteration.
- void oop_iterate(ExtendedOopClosure* cl);
void oop_iterate_no_header(OopClosure* cl);
void object_iterate(ObjectClosure* cl);
--- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -30,26 +30,22 @@
#include "gc/parallel/psParallelCompact.hpp"
#include "gc/parallel/psScavenge.hpp"
-inline size_t ParallelScavengeHeap::total_invocations()
-{
+inline size_t ParallelScavengeHeap::total_invocations() {
return UseParallelOldGC ? PSParallelCompact::total_invocations() :
PSMarkSweep::total_invocations();
}
-inline bool ParallelScavengeHeap::should_alloc_in_eden(const size_t size) const
-{
+inline bool ParallelScavengeHeap::should_alloc_in_eden(const size_t size) const {
const size_t eden_size = young_gen()->eden_space()->capacity_in_words();
return size < eden_size / 2;
}
-inline void ParallelScavengeHeap::invoke_scavenge()
-{
+inline void ParallelScavengeHeap::invoke_scavenge() {
PSScavenge::invoke();
}
inline bool ParallelScavengeHeap::is_in_young(oop p) {
// Assumes the the old gen address range is lower than that of the young gen.
- const void* loc = (void*) p;
bool result = ((HeapWord*)p) >= young_gen()->reserved().start();
assert(result == young_gen()->is_in_reserved(p),
err_msg("incorrect test - result=%d, p=" PTR_FORMAT, result, p2i((void*)p)));
--- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -299,7 +299,7 @@
// subtracted out.
size_t eden_limit = max_eden_size;
- const double gc_cost_limit = GCTimeLimit/100.0;
+ const double gc_cost_limit = GCTimeLimit / 100.0;
// Which way should we go?
// if pause requirement is not met
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -60,7 +60,7 @@
void PSMarkSweep::initialize() {
MemRegion mr = ParallelScavengeHeap::heap()->reserved_region();
- _ref_processor = new ReferenceProcessor(mr); // a vanilla ref proc
+ set_ref_processor(new ReferenceProcessor(mr)); // a vanilla ref proc
_counters = new CollectorCounters("PSMarkSweep", 1);
}
--- a/hotspot/src/share/vm/gc/parallel/psOldGen.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psOldGen.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -486,12 +486,12 @@
object_space()->verify();
}
class VerifyObjectStartArrayClosure : public ObjectClosure {
- PSOldGen* _gen;
+ PSOldGen* _old_gen;
ObjectStartArray* _start_array;
public:
- VerifyObjectStartArrayClosure(PSOldGen* gen, ObjectStartArray* start_array) :
- _gen(gen), _start_array(start_array) { }
+ VerifyObjectStartArrayClosure(PSOldGen* old_gen, ObjectStartArray* start_array) :
+ _old_gen(old_gen), _start_array(start_array) { }
virtual void do_object(oop obj) {
HeapWord* test_addr = (HeapWord*)obj + 1;
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -958,7 +958,7 @@
{
// Update the from & to space pointers in space_info, since they are swapped
// at each young gen gc. Do the update unconditionally (even though a
- // promotion failure does not swap spaces) because an unknown number of minor
+ // promotion failure does not swap spaces) because an unknown number of young
// collections will have swapped the spaces an unknown number of times.
GCTraceTime tm("pre compact", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -303,7 +303,7 @@
// completed(), which is desirable since a region must be claimed before it
// can be completed.
bool available() const { return _dc_and_los < dc_one; }
- bool claimed() const { return _dc_and_los >= dc_claimed; }
+ bool claimed() const { return _dc_and_los >= dc_claimed; }
bool completed() const { return _dc_and_los >= dc_completed; }
// These are not atomic.
@@ -979,7 +979,6 @@
static bool _dwl_initialized;
#endif // #ifdef ASSERT
-
public:
static ParallelOldTracer* gc_tracer() { return &_gc_tracer; }
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -597,9 +597,9 @@
// to allow resizes that may have been inhibited by the
// relative location of the "to" and "from" spaces.
- // Resizing the old gen at minor collects can cause increases
+ // Resizing the old gen at young collections can cause increases
// that don't feed back to the generation sizing policy until
- // a major collection. Don't resize the old gen here.
+ // a full collection. Don't resize the old gen here.
heap->resize_young_gen(size_policy->calculated_eden_size_in_bytes(),
size_policy->calculated_survivor_size_in_bytes());
--- a/hotspot/src/share/vm/gc/parallel/psTasks.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psTasks.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -172,10 +172,10 @@
void OldToYoungRootsTask::do_it(GCTaskManager* manager, uint which) {
// There are not old-to-young pointers if the old gen is empty.
- assert(!_gen->object_space()->is_empty(),
+ assert(!_old_gen->object_space()->is_empty(),
"Should not be called is there is no work");
- assert(_gen != NULL, "Sanity");
- assert(_gen->object_space()->contains(_gen_top) || _gen_top == _gen->object_space()->top(), "Sanity");
+ assert(_old_gen != NULL, "Sanity");
+ assert(_old_gen->object_space()->contains(_gen_top) || _gen_top == _old_gen->object_space()->top(), "Sanity");
assert(_stripe_number < ParallelGCThreads, "Sanity");
{
@@ -183,8 +183,8 @@
CardTableExtension* card_table =
barrier_set_cast<CardTableExtension>(ParallelScavengeHeap::heap()->barrier_set());
- card_table->scavenge_contents_parallel(_gen->start_array(),
- _gen->object_space(),
+ card_table->scavenge_contents_parallel(_old_gen->start_array(),
+ _old_gen->object_space(),
_gen_top,
pm,
_stripe_number,
--- a/hotspot/src/share/vm/gc/parallel/psTasks.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psTasks.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -160,17 +160,17 @@
class OldToYoungRootsTask : public GCTask {
private:
- PSOldGen* _gen;
+ PSOldGen* _old_gen;
HeapWord* _gen_top;
uint _stripe_number;
uint _stripe_total;
public:
- OldToYoungRootsTask(PSOldGen *gen,
+ OldToYoungRootsTask(PSOldGen *old_gen,
HeapWord* gen_top,
uint stripe_number,
uint stripe_total) :
- _gen(gen),
+ _old_gen(old_gen),
_gen_top(gen_top),
_stripe_number(stripe_number),
_stripe_total(stripe_total) { }
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -106,14 +106,14 @@
_gch(gch), _scan_cur_or_nonheap(cur), _scan_older(older)
{
assert(_gch->young_gen()->kind() == Generation::DefNew, "Generation should be DefNew");
- _gen = (DefNewGeneration*)_gch->young_gen();
+ _young_gen = (DefNewGeneration*)_gch->young_gen();
}
void DefNewGeneration::FastEvacuateFollowersClosure::do_void() {
do {
_gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older);
} while (!_gch->no_allocs_since_save_marks());
- guarantee(_gen->promo_failure_scan_is_complete(), "Failed to finish scan");
+ guarantee(_young_gen->promo_failure_scan_is_complete(), "Failed to finish scan");
}
ScanClosure::ScanClosure(DefNewGeneration* g, bool gc_barrier) :
@@ -200,8 +200,9 @@
_from_space = new ContiguousSpace();
_to_space = new ContiguousSpace();
- if (_eden_space == NULL || _from_space == NULL || _to_space == NULL)
+ if (_eden_space == NULL || _from_space == NULL || _to_space == NULL) {
vm_exit_during_initialization("Could not allocate a new gen space");
+ }
// Compute the maximum eden and survivor space sizes. These sizes
// are computed assuming the entire reserved space is committed.
@@ -655,7 +656,7 @@
if (ZapUnusedHeapArea) {
// This is now done here because of the piece-meal mangling which
// can check for valid mangling at intermediate points in the
- // collection(s). When a minor collection fails to collect
+ // collection(s). When a young collection fails to collect
// sufficient space resizing of the young generation can occur
// an redistribute the spaces in the young generation. Mangle
// here so that unzapped regions don't get distributed to
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -193,7 +193,7 @@
class FastEvacuateFollowersClosure: public VoidClosure {
GenCollectedHeap* _gch;
- DefNewGeneration* _gen;
+ DefNewGeneration* _young_gen;
FastScanClosure* _scan_cur_or_nonheap;
FastScanClosure* _scan_older;
public:
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -57,8 +57,8 @@
// each generation, allowing them in turn to examine the modified
// field.
//
- // We could check that p is also in an older generation, but
- // dirty cards in the youngest gen are never scanned, so the
+ // We could check that p is also in the old generation, but
+ // dirty cards in the young gen are never scanned, so the
// extra check probably isn't worthwhile.
if (GenCollectedHeap::heap()->is_in_reserved(p)) {
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
--- a/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -67,7 +67,7 @@
// hook up weak ref data so it can be used during Mark-Sweep
assert(ref_processor() == NULL, "no stomping");
assert(rp != NULL, "should be non-NULL");
- _ref_processor = rp;
+ set_ref_processor(rp);
rp->setup_policy(clear_all_softrefs);
GCTraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, _gc_tracer->gc_id());
@@ -136,7 +136,7 @@
}
// refs processing: clean slate
- _ref_processor = NULL;
+ set_ref_processor(NULL);
// Update heap occupancy information which is used as
// input to soft ref clearing policy at the next gc.
--- a/hotspot/src/share/vm/gc/serial/markSweep.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/markSweep.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -28,11 +28,20 @@
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
+#include "gc/shared/specialized_oop_closures.hpp"
+#include "memory/iterator.inline.hpp"
+#include "oops/instanceClassLoaderKlass.inline.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/instanceMirrorKlass.inline.hpp"
+#include "oops/instanceRefKlass.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
+#include "utilities/macros.hpp"
+#include "utilities/stack.inline.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1StringDedup.hpp"
+#endif // INCLUDE_ALL_GCS
uint MarkSweep::_total_invocations = 0;
@@ -50,176 +59,101 @@
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
-void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); }
-void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
-
-MarkSweep::MarkAndPushClosure MarkSweep::mark_and_push_closure;
+MarkAndPushClosure MarkSweep::mark_and_push_closure;
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure);
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure);
-template <typename T>
-void MarkSweep::MarkAndPushClosure::do_oop_nv(T* p) { mark_and_push(p); }
-void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { do_oop_nv(p); }
-void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+inline void MarkSweep::mark_object(oop obj) {
+#if INCLUDE_ALL_GCS
+ if (G1StringDedup::is_enabled()) {
+ // We must enqueue the object before it is marked
+ // as we otherwise can't read the object's age.
+ G1StringDedup::enqueue_from_mark(obj);
+ }
+#endif
+ // some marks may contain information we need to preserve so we store them away
+ // and overwrite the mark. We'll restore it at the end of markSweep.
+ markOop mark = obj->mark();
+ obj->set_mark(markOopDesc::prototype()->set_marked());
-void MarkSweep::follow_class_loader(ClassLoaderData* cld) {
- MarkSweep::follow_cld_closure.do_cld(cld);
-}
-
-void InstanceKlass::oop_ms_follow_contents(oop obj) {
- assert(obj != NULL, "can't follow the content of NULL object");
- MarkSweep::follow_klass(this);
-
- oop_oop_iterate_oop_maps<true>(obj, &MarkSweep::mark_and_push_closure);
+ if (mark->must_be_preserved(obj)) {
+ preserve_mark(obj, mark);
+ }
}
-void InstanceMirrorKlass::oop_ms_follow_contents(oop obj) {
- InstanceKlass::oop_ms_follow_contents(obj);
-
- // Follow the klass field in the mirror
- Klass* klass = java_lang_Class::as_Klass(obj);
- if (klass != NULL) {
- // An anonymous class doesn't have its own class loader, so the call
- // to follow_klass will mark and push its java mirror instead of the
- // class loader. When handling the java mirror for an anonymous class
- // we need to make sure its class loader data is claimed, this is done
- // by calling follow_class_loader explicitly. For non-anonymous classes
- // the call to follow_class_loader is made when the class loader itself
- // is handled.
- if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
- MarkSweep::follow_class_loader(klass->class_loader_data());
- } else {
- MarkSweep::follow_klass(klass);
+template <class T> inline void MarkSweep::mark_and_push(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ if (!obj->mark()->is_marked() &&
+ !is_archive_object(obj)) {
+ mark_object(obj);
+ _marking_stack.push(obj);
}
- } else {
- // If klass is NULL then this a mirror for a primitive type.
- // We don't have to follow them, since they are handled as strong
- // roots in Universe::oops_do.
- assert(java_lang_Class::is_primitive(obj), "Sanity check");
- }
-
- oop_oop_iterate_statics<true>(obj, &MarkSweep::mark_and_push_closure);
-}
-
-void InstanceClassLoaderKlass::oop_ms_follow_contents(oop obj) {
- InstanceKlass::oop_ms_follow_contents(obj);
-
- ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj);
-
- // We must NULL check here, since the class loader
- // can be found before the loader data has been set up.
- if(loader_data != NULL) {
- MarkSweep::follow_class_loader(loader_data);
}
}
-template <class T>
-static void oop_ms_follow_contents_specialized(InstanceRefKlass* klass, oop obj) {
- T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
- T heap_oop = oopDesc::load_heap_oop(referent_addr);
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr("InstanceRefKlass::oop_ms_follow_contents_specialized " PTR_FORMAT, p2i(obj));
- }
- )
- if (!oopDesc::is_null(heap_oop)) {
- oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
- if (!referent->is_gc_marked() &&
- MarkSweep::ref_processor()->discover_reference(obj, klass->reference_type())) {
- // reference was discovered, referent will be traversed later
- klass->InstanceKlass::oop_ms_follow_contents(obj);
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" Non NULL enqueued " PTR_FORMAT, p2i(obj));
- }
- )
- return;
- } else {
- // treat referent as normal oop
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" Non NULL normal " PTR_FORMAT, p2i(obj));
- }
- )
- MarkSweep::mark_and_push(referent_addr);
- }
- }
- T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
- // Treat discovered as normal oop, if ref is not "active",
- // i.e. if next is non-NULL.
- T next_oop = oopDesc::load_heap_oop(next_addr);
- if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
- T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" Process discovered as normal "
- PTR_FORMAT, p2i(discovered_addr));
- }
- )
- MarkSweep::mark_and_push(discovered_addr);
- }
- // treat next as normal oop. next is a link in the reference queue.
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" Process next as normal " PTR_FORMAT, p2i(next_addr));
- }
- )
- MarkSweep::mark_and_push(next_addr);
- klass->InstanceKlass::oop_ms_follow_contents(obj);
+inline void MarkSweep::follow_klass(Klass* klass) {
+ oop op = klass->klass_holder();
+ MarkSweep::mark_and_push(&op);
+}
+
+inline void MarkSweep::follow_cld(ClassLoaderData* cld) {
+ MarkSweep::follow_cld_closure.do_cld(cld);
}
-void InstanceRefKlass::oop_ms_follow_contents(oop obj) {
- if (UseCompressedOops) {
- oop_ms_follow_contents_specialized<narrowOop>(this, obj);
- } else {
- oop_ms_follow_contents_specialized<oop>(this, obj);
+template <typename T>
+inline void MarkAndPushClosure::do_oop_nv(T* p) { MarkSweep::mark_and_push(p); }
+void MarkAndPushClosure::do_oop(oop* p) { do_oop_nv(p); }
+void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+inline bool MarkAndPushClosure::do_metadata_nv() { return true; }
+bool MarkAndPushClosure::do_metadata() { return do_metadata_nv(); }
+inline void MarkAndPushClosure::do_klass_nv(Klass* k) { MarkSweep::follow_klass(k); }
+void MarkAndPushClosure::do_klass(Klass* k) { do_klass_nv(k); }
+inline void MarkAndPushClosure::do_cld_nv(ClassLoaderData* cld) { MarkSweep::follow_cld(cld); }
+void MarkAndPushClosure::do_cld(ClassLoaderData* cld) { do_cld_nv(cld); }
+
+template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
+ mark_and_push(p);
+}
+
+void MarkSweep::push_objarray(oop obj, size_t index) {
+ ObjArrayTask task(obj, index);
+ assert(task.is_valid(), "bad ObjArrayTask");
+ _objarray_stack.push(task);
+}
+
+inline void MarkSweep::follow_array(objArrayOop array) {
+ MarkSweep::follow_klass(array->klass());
+ // Don't push empty arrays to avoid unnecessary work.
+ if (array->length() > 0) {
+ MarkSweep::push_objarray(array, 0);
}
}
-template <class T>
-static void oop_ms_follow_contents_specialized(oop obj, int index) {
- objArrayOop a = objArrayOop(obj);
- const size_t len = size_t(a->length());
- const size_t beg_index = size_t(index);
- assert(beg_index < len || len == 0, "index too large");
-
- const size_t stride = MIN2(len - beg_index, ObjArrayMarkingStride);
- const size_t end_index = beg_index + stride;
- T* const base = (T*)a->base();
- T* const beg = base + beg_index;
- T* const end = base + end_index;
-
- // Push the non-NULL elements of the next stride on the marking stack.
- for (T* e = beg; e < end; e++) {
- MarkSweep::mark_and_push<T>(e);
- }
-
- if (end_index < len) {
- MarkSweep::push_objarray(a, end_index); // Push the continuation.
+inline void MarkSweep::follow_object(oop obj) {
+ assert(obj->is_gc_marked(), "should be marked");
+ if (obj->is_objArray()) {
+ // Handle object arrays explicitly to allow them to
+ // be split into chunks if needed.
+ MarkSweep::follow_array((objArrayOop)obj);
+ } else {
+ obj->oop_iterate(&mark_and_push_closure);
}
}
-void ObjArrayKlass::oop_ms_follow_contents(oop obj) {
- assert (obj->is_array(), "obj must be array");
- MarkSweep::follow_klass(this);
- if (UseCompressedOops) {
- oop_ms_follow_contents_specialized<narrowOop>(obj, 0);
- } else {
- oop_ms_follow_contents_specialized<oop>(obj, 0);
- }
-}
+void MarkSweep::follow_array_chunk(objArrayOop array, int index) {
+ const int len = array->length();
+ const int beg_index = index;
+ assert(beg_index < len || len == 0, "index too large");
-void TypeArrayKlass::oop_ms_follow_contents(oop obj) {
- assert(obj->is_typeArray(),"must be a type array");
- // Performance tweak: We skip iterating over the klass pointer since we
- // know that Universe::TypeArrayKlass never moves.
-}
+ const int stride = MIN2(len - beg_index, (int) ObjArrayMarkingStride);
+ const int end_index = beg_index + stride;
-void MarkSweep::follow_array(objArrayOop array, int index) {
- if (UseCompressedOops) {
- oop_ms_follow_contents_specialized<narrowOop>(array, index);
- } else {
- oop_ms_follow_contents_specialized<oop>(array, index);
+ array->oop_iterate_range(&mark_and_push_closure, beg_index, end_index);
+
+ if (end_index < len) {
+ MarkSweep::push_objarray(array, end_index); // Push the continuation.
}
}
@@ -233,7 +167,7 @@
// Process ObjArrays one at a time to avoid marking stack bloat.
if (!_objarray_stack.is_empty()) {
ObjArrayTask task = _objarray_stack.pop();
- follow_array(objArrayOop(task.obj()), task.index());
+ follow_array_chunk(objArrayOop(task.obj()), task.index());
}
} while (!_marking_stack.is_empty() || !_objarray_stack.is_empty());
}
@@ -242,6 +176,24 @@
void MarkSweep::FollowStackClosure::do_void() { follow_stack(); }
+template <class T> inline void MarkSweep::follow_root(T* p) {
+ assert(!Universe::heap()->is_in_reserved(p),
+ "roots shouldn't be things within the heap");
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ if (!obj->mark()->is_marked() &&
+ !is_archive_object(obj)) {
+ mark_object(obj);
+ follow_object(obj);
+ }
+ }
+ follow_stack();
+}
+
+void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); }
+void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
+
void PreservedMark::adjust_pointer() {
MarkSweep::adjust_pointer(&_obj);
}
@@ -266,6 +218,11 @@
}
}
+void MarkSweep::set_ref_processor(ReferenceProcessor* rp) {
+ _ref_processor = rp;
+ mark_and_push_closure.set_ref_processor(_ref_processor);
+}
+
MarkSweep::AdjustPointerClosure MarkSweep::adjust_pointer_closure;
template <typename T>
@@ -405,3 +362,6 @@
// know that Universe::TypeArrayKlass never moves.
return t->object_size();
}
+
+// Generate MS specialized oop_oop_iterate functions.
+SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(ALL_KLASS_OOP_OOP_ITERATE_DEFN)
--- a/hotspot/src/share/vm/gc/serial/markSweep.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/markSweep.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -49,6 +49,7 @@
// declared at end
class PreservedMark;
+class MarkAndPushClosure;
class MarkSweep : AllStatic {
//
@@ -60,13 +61,6 @@
virtual void do_oop(narrowOop* p);
};
- class MarkAndPushClosure: public ExtendedOopClosure {
- public:
- template <typename T> void do_oop_nv(T* p);
- virtual void do_oop(oop* p);
- virtual void do_oop(narrowOop* p);
- };
-
class FollowStackClosure: public VoidClosure {
public:
virtual void do_void();
@@ -146,6 +140,7 @@
// Reference Processing
static ReferenceProcessor* const ref_processor() { return _ref_processor; }
+ static void set_ref_processor(ReferenceProcessor* rp);
// Archive Object handling
static inline bool is_archive_object(oop object);
@@ -153,34 +148,55 @@
static STWGCTimer* gc_timer() { return _gc_timer; }
static SerialOldTracer* gc_tracer() { return _gc_tracer; }
+ static void preserve_mark(oop p, markOop mark);
+ // Save the mark word so it can be restored later
+ static void adjust_marks(); // Adjust the pointers in the preserved marks table
+ static void restore_marks(); // Restore the marks that we saved in preserve_mark
+
+ static int adjust_pointers(oop obj);
+
+ static void follow_stack(); // Empty marking stack.
+
+ static void follow_klass(Klass* klass);
+
+ static void follow_cld(ClassLoaderData* cld);
+
+ template <class T> static inline void adjust_pointer(T* p);
+
+ // Check mark and maybe push on marking stack
+ template <class T> static void mark_and_push(T* p);
+
+ private:
// Call backs for marking
static void mark_object(oop obj);
// Mark pointer and follow contents. Empty marking stack afterwards.
template <class T> static inline void follow_root(T* p);
- // Check mark and maybe push on marking stack
- template <class T> static void mark_and_push(T* p);
-
static inline void push_objarray(oop obj, size_t index);
- static void follow_stack(); // Empty marking stack.
-
static void follow_object(oop obj);
- static void follow_array(objArrayOop array, int index);
+ static void follow_array(objArrayOop array);
+
+ static void follow_array_chunk(objArrayOop array, int index);
+};
- static void follow_klass(Klass* klass);
-
- static void follow_class_loader(ClassLoaderData* cld);
+class MarkAndPushClosure: public ExtendedOopClosure {
+public:
+ template <typename T> void do_oop_nv(T* p);
+ virtual void do_oop(oop* p);
+ virtual void do_oop(narrowOop* p);
- static int adjust_pointers(oop obj);
+ virtual bool do_metadata();
+ bool do_metadata_nv();
- static void preserve_mark(oop p, markOop mark);
- // Save the mark word so it can be restored later
- static void adjust_marks(); // Adjust the pointers in the preserved marks table
- static void restore_marks(); // Restore the marks that we saved in preserve_mark
+ virtual void do_klass(Klass* k);
+ void do_klass_nv(Klass* k);
- template <class T> static inline void adjust_pointer(T* p);
+ virtual void do_cld(ClassLoaderData* cld);
+ void do_cld_nv(ClassLoaderData* cld);
+
+ void set_ref_processor(ReferenceProcessor* rp) { _ref_processor = rp; }
};
class PreservedMark VALUE_OBJ_CLASS_SPEC {
--- a/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/markSweep.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -26,38 +26,13 @@
#define SHARE_VM_GC_SERIAL_MARKSWEEP_INLINE_HPP
#include "gc/serial/markSweep.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "oops/instanceClassLoaderKlass.inline.hpp"
-#include "oops/instanceKlass.inline.hpp"
-#include "oops/instanceMirrorKlass.inline.hpp"
-#include "oops/instanceRefKlass.inline.hpp"
+#include "memory/universe.hpp"
#include "oops/markOop.inline.hpp"
-#include "oops/objArrayKlass.inline.hpp"
-#include "utilities/macros.hpp"
-#include "utilities/stack.inline.hpp"
+#include "oops/oop.inline.hpp"
#if INCLUDE_ALL_GCS
-#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/g1MarkSweep.hpp"
#endif // INCLUDE_ALL_GCS
-inline void MarkSweep::mark_object(oop obj) {
-#if INCLUDE_ALL_GCS
- if (G1StringDedup::is_enabled()) {
- // We must enqueue the object before it is marked
- // as we otherwise can't read the object's age.
- G1StringDedup::enqueue_from_mark(obj);
- }
-#endif
- // some marks may contain information we need to preserve so we store them away
- // and overwrite the mark. We'll restore it at the end of markSweep.
- markOop mark = obj->mark();
- obj->set_mark(markOopDesc::prototype()->set_marked());
-
- if (mark->must_be_preserved(obj)) {
- preserve_mark(obj, mark);
- }
-}
-
inline bool MarkSweep::is_archive_object(oop object) {
#if INCLUDE_ALL_GCS
return (G1MarkSweep::archive_check_enabled() &&
@@ -67,51 +42,6 @@
#endif
}
-inline void MarkSweep::follow_klass(Klass* klass) {
- oop op = klass->klass_holder();
- MarkSweep::mark_and_push(&op);
-}
-
-inline void MarkSweep::follow_object(oop obj) {
- assert(obj->is_gc_marked(), "should be marked");
-
- obj->ms_follow_contents();
-}
-
-template <class T> inline void MarkSweep::follow_root(T* p) {
- assert(!Universe::heap()->is_in_reserved(p),
- "roots shouldn't be things within the heap");
- T heap_oop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(heap_oop)) {
- oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- if (!obj->mark()->is_marked() &&
- !is_archive_object(obj)) {
- mark_object(obj);
- follow_object(obj);
- }
- }
- follow_stack();
-}
-
-template <class T> inline void MarkSweep::mark_and_push(T* p) {
-// assert(Universe::heap()->is_in_reserved(p), "should be in object space");
- T heap_oop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(heap_oop)) {
- oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- if (!obj->mark()->is_marked() &&
- !is_archive_object(obj)) {
- mark_object(obj);
- _marking_stack.push(obj);
- }
- }
-}
-
-void MarkSweep::push_objarray(oop obj, size_t index) {
- ObjArrayTask task(obj, index);
- assert(task.is_valid(), "bad ObjArrayTask");
- _objarray_stack.push(task);
-}
-
inline int MarkSweep::adjust_pointers(oop obj) {
return obj->ms_adjust_pointers();
}
@@ -139,8 +69,4 @@
}
}
-template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
- mark_and_push(p);
-}
-
#endif // SHARE_VM_GC_SERIAL_MARKSWEEP_INLINE_HPP
--- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -108,7 +108,7 @@
free());
}
}
- // If we had to expand to accommodate promotions from younger generations
+ // If we had to expand to accommodate promotions from the young generation
if (!result && _capacity_at_prologue < capacity()) {
result = true;
if (PrintGC && Verbose) {
@@ -140,11 +140,11 @@
// that are of interest at this point.
bool current_is_young = GenCollectedHeap::heap()->is_young_gen(current_generation);
if (!full && current_is_young) {
- // Calculate size of data promoted from the younger generations
+ // Calculate size of data promoted from the young generation
// before doing the collection.
size_t used_before_gc = used();
- // If the younger gen collections were skipped, then the
+ // If the young gen collection was skipped, then the
// number of promoted bytes will be 0 and adding it to the
// average will incorrectly lessen the average. It is, however,
// also possible that no promotion was needed.
--- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -42,10 +42,10 @@
friend class VM_PopulateDumpSharedSpace;
protected:
- ContiguousSpace* _the_space; // Actual space holding objects
+ ContiguousSpace* _the_space; // Actual space holding objects
- GenerationCounters* _gen_counters;
- CSpaceCounters* _space_counters;
+ GenerationCounters* _gen_counters;
+ CSpaceCounters* _space_counters;
// Allocation failure
virtual bool expand(size_t bytes, size_t expand_bytes);
@@ -54,6 +54,7 @@
ContiguousSpace* space() const { return _the_space; }
void assert_correct_size_change_locking();
+
public:
TenuredGeneration(ReservedSpace rs,
size_t initial_byte_size,
@@ -66,10 +67,9 @@
const char* short_name() const { return "Tenured"; }
// Does a "full" (forced) collection invoked on this generation collect
- // all younger generations as well? Note that this is a
- // hack to allow the collection of the younger gen first if the flag is
- // set.
- virtual bool full_collects_younger_generations() const {
+ // the young generation as well? Note that this is a hack to allow the
+ // collection of the young gen first if the flag is set.
+ virtual bool full_collects_young_generation() const {
return !ScavengeBeforeFullGC;
}
@@ -99,15 +99,16 @@
bool clear_all_soft_refs,
size_t size,
bool is_tlab);
+
HeapWord* expand_and_allocate(size_t size,
bool is_tlab,
bool parallel = false);
virtual void prepare_for_verify();
-
virtual void gc_prologue(bool full);
virtual void gc_epilogue(bool full);
+
bool should_collect(bool full,
size_t word_size,
bool is_tlab);
--- a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -266,22 +266,22 @@
}
// The policy does not have enough data until at least some
- // minor collections have been done.
+ // young collections have been done.
_young_gen_policy_is_ready =
(_avg_minor_gc_cost->count() >= AdaptiveSizePolicyReadyThreshold);
// Calculate variables used to estimate pause time vs. gen sizes
- double eden_size_in_mbytes = ((double)_eden_size)/((double)M);
+ double eden_size_in_mbytes = ((double)_eden_size) / ((double)M);
update_minor_pause_young_estimator(minor_pause_in_ms);
update_minor_pause_old_estimator(minor_pause_in_ms);
if (PrintAdaptiveSizePolicy && Verbose) {
gclog_or_tty->print("AdaptiveSizePolicy::minor_collection_end: "
- "minor gc cost: %f average: %f", collection_cost,
- _avg_minor_gc_cost->average());
+ "minor gc cost: %f average: %f", collection_cost,
+ _avg_minor_gc_cost->average());
gclog_or_tty->print_cr(" minor pause: %f minor period %f",
- minor_pause_in_ms,
- _latest_minor_mutator_interval_seconds * MILLIUNITS);
+ minor_pause_in_ms,
+ _latest_minor_mutator_interval_seconds * MILLIUNITS);
}
// Calculate variable used to estimate collection cost vs. gen sizes
@@ -295,8 +295,7 @@
_minor_timer.start();
}
-size_t AdaptiveSizePolicy::eden_increment(size_t cur_eden,
- uint percent_change) {
+size_t AdaptiveSizePolicy::eden_increment(size_t cur_eden, uint percent_change) {
size_t eden_heap_delta;
eden_heap_delta = cur_eden / 100 * percent_change;
return eden_heap_delta;
@@ -312,8 +311,7 @@
return eden_heap_delta;
}
-size_t AdaptiveSizePolicy::promo_increment(size_t cur_promo,
- uint percent_change) {
+size_t AdaptiveSizePolicy::promo_increment(size_t cur_promo, uint percent_change) {
size_t promo_heap_delta;
promo_heap_delta = cur_promo / 100 * percent_change;
return promo_heap_delta;
--- a/hotspot/src/share/vm/gc/shared/barrierSet.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/barrierSet.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -132,6 +132,9 @@
// First the pre-write versions...
template <class T> inline void write_ref_field_pre(T* field, oop new_val);
private:
+ // Helper for write_ref_field_pre and friends, testing for specialized cases.
+ bool devirtualize_reference_writes() const;
+
// Keep this private so as to catch violations at build time.
virtual void write_ref_field_pre_work( void* field, oop new_val) { guarantee(false, "Not needed"); };
protected:
@@ -142,7 +145,7 @@
// ...then the post-write version.
inline void write_ref_field(void* field, oop new_val, bool release = false);
protected:
- virtual void write_ref_field_work(void* field, oop new_val, bool release = false) = 0;
+ virtual void write_ref_field_work(void* field, oop new_val, bool release) = 0;
public:
// Invoke the barrier, if any, necessary when writing the "bytes"-byte
--- a/hotspot/src/share/vm/gc/shared/barrierSet.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/barrierSet.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -32,8 +32,18 @@
// performance-critical calls when the barrier is the most common
// card-table kind.
+inline bool BarrierSet::devirtualize_reference_writes() const {
+ switch (kind()) {
+ case CardTableForRS:
+ case CardTableExtension:
+ return true;
+ default:
+ return false;
+ }
+}
+
template <class T> void BarrierSet::write_ref_field_pre(T* field, oop new_val) {
- if (kind() == CardTableModRef) {
+ if (devirtualize_reference_writes()) {
barrier_set_cast<CardTableModRefBS>(this)->inline_write_ref_field_pre(field, new_val);
} else {
write_ref_field_pre_work(field, new_val);
@@ -41,7 +51,7 @@
}
void BarrierSet::write_ref_field(void* field, oop new_val, bool release) {
- if (kind() == CardTableModRef) {
+ if (devirtualize_reference_writes()) {
barrier_set_cast<CardTableModRefBS>(this)->inline_write_ref_field(field, new_val, release);
} else {
write_ref_field_work(field, new_val, release);
@@ -77,7 +87,7 @@
inline void BarrierSet::write_region(MemRegion mr) {
- if (kind() == CardTableModRef) {
+ if (devirtualize_reference_writes()) {
barrier_set_cast<CardTableModRefBS>(this)->inline_write_region(mr);
} else {
write_region_work(mr);
--- a/hotspot/src/share/vm/gc/shared/blockOffsetTable.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/blockOffsetTable.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -25,9 +25,12 @@
#ifndef SHARE_VM_GC_SHARED_BLOCKOFFSETTABLE_HPP
#define SHARE_VM_GC_SHARED_BLOCKOFFSETTABLE_HPP
+#include "gc/shared/memset_with_concurrent_readers.hpp"
#include "memory/memRegion.hpp"
#include "memory/virtualspace.hpp"
+#include "runtime/globals.hpp"
#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
// The CollectedHeap type requires subtypes to implement a method
// "block_start". For some subtypes, notably generational
@@ -126,6 +129,19 @@
VirtualSpace _vs;
u_char* _offset_array; // byte array keeping backwards offsets
+ void fill_range(size_t start, size_t num_cards, u_char offset) {
+ void* start_ptr = &_offset_array[start];
+#if INCLUDE_ALL_GCS
+ // If collector is concurrent, special handling may be needed.
+ assert(!UseG1GC, "Shouldn't be here when using G1");
+ if (UseConcMarkSweepGC) {
+ memset_with_concurrent_readers(start_ptr, offset, num_cards);
+ return;
+ }
+#endif // INCLUDE_ALL_GCS
+ memset(start_ptr, offset, num_cards);
+ }
+
protected:
// Bounds checking accessors:
// For performance these have to devolve to array accesses in product builds.
@@ -160,20 +176,7 @@
assert(left < right, "Heap addresses out of order");
size_t num_cards = pointer_delta(right, left) >> LogN_words;
- // Below, we may use an explicit loop instead of memset()
- // because on certain platforms memset() can give concurrent
- // readers "out-of-thin-air," phantom zeros; see 6948537.
- if (UseMemSetInBOT) {
- memset(&_offset_array[index_for(left)], offset, num_cards);
- } else {
- size_t i = index_for(left);
- const size_t end = i + num_cards;
- for (; i < end; i++) {
- // Elided until CR 6977974 is fixed properly.
- // assert(!reducing || _offset_array[i] >= offset, "Not reducing");
- _offset_array[i] = offset;
- }
- }
+ fill_range(index_for(left), num_cards, offset);
}
void set_offset_array(size_t left, size_t right, u_char offset, bool reducing = false) {
@@ -182,20 +185,7 @@
assert(left <= right, "indexes out of order");
size_t num_cards = right - left + 1;
- // Below, we may use an explicit loop instead of memset
- // because on certain platforms memset() can give concurrent
- // readers "out-of-thin-air," phantom zeros; see 6948537.
- if (UseMemSetInBOT) {
- memset(&_offset_array[left], offset, num_cards);
- } else {
- size_t i = left;
- const size_t end = i + num_cards;
- for (; i < end; i++) {
- // Elided until CR 6977974 is fixed properly.
- // assert(!reducing || _offset_array[i] >= offset, "Not reducing");
- _offset_array[i] = offset;
- }
- }
+ fill_range(left, num_cards, offset);
}
void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const {
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -183,7 +183,7 @@
// these functions here for performance.
void write_ref_field_work(oop obj, size_t offset, oop newVal);
- virtual void write_ref_field_work(void* field, oop newVal, bool release = false);
+ virtual void write_ref_field_work(void* field, oop newVal, bool release);
public:
bool has_write_ref_array_opt() { return true; }
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -31,13 +31,7 @@
CardTableModRefBSForCTRS::CardTableModRefBSForCTRS(MemRegion whole_heap) :
CardTableModRefBS(
whole_heap,
- // Concrete tag should be BarrierSet::CardTableForRS.
- // That will presently break things in a bunch of places though.
- // The concrete tag is used as a dispatch key in many places, and
- // CardTableForRS does not correctly dispatch in some of those
- // uses. This will be addressed as part of a reorganization of the
- // BarrierSet hierarchy.
- BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableForRS)),
+ BarrierSet::FakeRtti(BarrierSet::CardTableForRS)),
// LNC functionality
_lowest_non_clean(NULL),
_lowest_non_clean_chunk_size(NULL),
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -80,7 +80,9 @@
break;
}
}
- if (!seen) return v;
+ if (!seen) {
+ return v;
+ }
}
ShouldNotReachHere();
return 0;
@@ -502,7 +504,7 @@
//
// The main point below is that the parallel card scanning code
// deals correctly with these stale card values. There are two main
- // cases to consider where we have a stale "younger gen" value and a
+ // cases to consider where we have a stale "young gen" value and a
// "derivative" case to consider, where we have a stale
// "cur_younger_gen_and_prev_non_clean" value, as will become
// apparent in the case analysis below.
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -160,16 +160,20 @@
// Memory state functions.
-CollectedHeap::CollectedHeap() {
+CollectedHeap::CollectedHeap() :
+ _barrier_set(NULL),
+ _is_gc_active(false),
+ _total_collections(0),
+ _total_full_collections(0),
+ _gc_cause(GCCause::_no_gc),
+ _gc_lastcause(GCCause::_no_gc),
+ _defer_initial_card_mark(false) // strengthened by subclass in pre_initialize() below.
+{
const size_t max_len = size_t(arrayOopDesc::max_array_length(T_INT));
const size_t elements_per_word = HeapWordSize / sizeof(jint);
_filler_array_max_size = align_object_size(filler_array_hdr_size() +
max_len / elements_per_word);
- _barrier_set = NULL;
- _is_gc_active = false;
- _total_collections = _total_full_collections = 0;
- _gc_cause = _gc_lastcause = GCCause::_no_gc;
NOT_PRODUCT(_promotion_failure_alot_count = 0;)
NOT_PRODUCT(_promotion_failure_alot_gc_number = 0;)
@@ -184,7 +188,7 @@
PerfDataManager::create_string_variable(SUN_GC, "lastCause",
80, GCCause::to_string(_gc_lastcause), CHECK);
}
- _defer_initial_card_mark = false; // strengthened by subclass in pre_initialize() below.
+
// Create the ring log
if (LogEvents) {
_gc_heap_log = new GCHeapLog();
@@ -570,8 +574,8 @@
void CollectedHeap::pre_full_gc_dump(GCTimer* timer) {
if (HeapDumpBeforeFullGC) {
GCTraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, timer, GCId::create());
- // We are doing a "major" collection and a heap dump before
- // major collection has been requested.
+ // We are doing a full collection and a heap dump before
+ // full collection has been requested.
HeapDumper::dump_heap();
}
if (PrintClassHistogramBeforeFullGC) {
--- a/hotspot/src/share/vm/gc/shared/collectorPolicy.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/collectorPolicy.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -111,13 +111,6 @@
size_t max_heap_byte_size() { return _max_heap_byte_size; }
size_t min_heap_byte_size() { return _min_heap_byte_size; }
- enum Name {
- CollectorPolicyKind,
- GenCollectorPolicyKind,
- ConcurrentMarkSweepPolicyKind,
- G1CollectorPolicyKind
- };
-
AdaptiveSizePolicy* size_policy() { return _size_policy; }
bool should_clear_all_soft_refs() { return _should_clear_all_soft_refs; }
void set_should_clear_all_soft_refs(bool v) { _should_clear_all_soft_refs = v; }
@@ -150,8 +143,6 @@
#endif // INCLUDE_ALL_GCS
- virtual BarrierSet::Name barrier_set_name() = 0;
-
virtual GenRemSet* create_rem_set(MemRegion reserved);
// This method controls how a collector satisfies a request
@@ -182,10 +173,6 @@
ShouldNotReachHere();
}
- virtual CollectorPolicy::Name kind() {
- return CollectorPolicy::CollectorPolicyKind;
- }
-
// Do any updates required to global flags that are due to heap initialization
// changes
virtual void post_heap_initialize() = 0;
@@ -298,12 +285,6 @@
virtual void post_heap_initialize() {
assert(_max_young_size == MaxNewSize, "Should be taken care of by initialize_size_info");
}
-
- BarrierSet::Name barrier_set_name() { return BarrierSet::CardTableModRef; }
-
- virtual CollectorPolicy::Name kind() {
- return CollectorPolicy::GenCollectorPolicyKind;
- }
};
class MarkSweepPolicy : public GenCollectorPolicy {
--- a/hotspot/src/share/vm/gc/shared/gcTrace.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/gcTrace.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -88,6 +88,8 @@
send_reference_stats_event(REF_WEAK, rps.weak_count());
send_reference_stats_event(REF_FINAL, rps.final_count());
send_reference_stats_event(REF_PHANTOM, rps.phantom_count());
+ send_reference_stats_event(REF_CLEANER, rps.cleaner_count());
+ send_reference_stats_event(REF_JNI, rps.jni_weak_ref_count());
}
#if INCLUDE_SERVICES
@@ -173,6 +175,11 @@
_tenuring_threshold = tenuring_threshold;
}
+bool YoungGCTracer::should_report_promotion_events() const {
+ return should_report_promotion_in_new_plab_event() ||
+ should_report_promotion_outside_plab_event();
+}
+
bool YoungGCTracer::should_report_promotion_in_new_plab_event() const {
return should_send_promotion_in_new_plab_event();
}
--- a/hotspot/src/share/vm/gc/shared/gcTrace.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/gcTrace.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -172,6 +172,7 @@
*
* plab_size is the size of the newly allocated PLAB in bytes.
*/
+ bool should_report_promotion_events() const;
bool should_report_promotion_in_new_plab_event() const;
bool should_report_promotion_outside_plab_event() const;
void report_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -464,7 +464,7 @@
bool prepared_for_verification = false;
bool collected_old = false;
bool old_collects_young = complete &&
- _old_gen->full_collects_younger_generations();
+ _old_gen->full_collects_young_generation();
if (!old_collects_young &&
_young_gen->should_collect(full, size, is_tlab)) {
if (run_verification && VerifyGCLevel <= 0 && VerifyBeforeGC) {
@@ -521,7 +521,7 @@
// a whole heap collection.
complete = complete || collected_old;
- if (complete) { // We did a "major" collection
+ if (complete) { // We did a full collection
// FIXME: See comment at pre_full_gc_dump call
post_full_gc_dump(NULL); // do any post full gc dumps
}
@@ -668,13 +668,13 @@
void GenCollectedHeap::gen_process_roots(StrongRootsScope* scope,
GenerationType type,
- bool younger_gens_as_roots,
+ bool young_gen_as_roots,
ScanningOption so,
bool only_strong_roots,
OopsInGenClosure* not_older_gens,
OopsInGenClosure* older_gens,
CLDClosure* cld_closure) {
- const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots;
+ const bool is_adjust_phase = !only_strong_roots && !young_gen_as_roots;
bool is_moving_collection = false;
if (type == YoungGen || is_adjust_phase) {
@@ -691,7 +691,7 @@
cld_closure, weak_cld_closure,
&mark_code_closure);
- if (younger_gens_as_roots) {
+ if (young_gen_as_roots) {
if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
if (type == OldGen) {
not_older_gens->set_generation(_young_gen);
@@ -763,25 +763,25 @@
void GenCollectedHeap::collect(GCCause::Cause cause) {
if (should_do_concurrent_full_gc(cause)) {
#if INCLUDE_ALL_GCS
- // mostly concurrent full collection
+ // Mostly concurrent full collection.
collect_mostly_concurrent(cause);
#else // INCLUDE_ALL_GCS
ShouldNotReachHere();
#endif // INCLUDE_ALL_GCS
} else if (cause == GCCause::_wb_young_gc) {
- // minor collection for WhiteBox API
+ // Young collection for the WhiteBox API.
collect(cause, YoungGen);
} else {
#ifdef ASSERT
if (cause == GCCause::_scavenge_alot) {
- // minor collection only
+ // Young collection only.
collect(cause, YoungGen);
} else {
- // Stop-the-world full collection
+ // Stop-the-world full collection.
collect(cause, OldGen);
}
#else
- // Stop-the-world full collection
+ // Stop-the-world full collection.
collect(cause, OldGen);
#endif
}
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -173,8 +173,7 @@
size_t max_capacity() const;
- HeapWord* mem_allocate(size_t size,
- bool* gc_overhead_limit_was_exceeded);
+ HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded);
// We may support a shared contiguous allocation area, if the youngest
// generation does.
@@ -403,7 +402,7 @@
void gen_process_roots(StrongRootsScope* scope,
GenerationType type,
- bool younger_gens_as_roots,
+ bool young_gen_as_roots,
ScanningOption so,
bool only_strong_roots,
OopsInGenClosure* not_older_gens,
--- a/hotspot/src/share/vm/gc/shared/genRemSet.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/genRemSet.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -110,13 +110,11 @@
virtual void print() {}
// Informs the RS that the given memregion contains no references to
- // younger generations.
+ // the young generation.
virtual void clear(MemRegion mr) = 0;
- // Informs the RS that there are no references to generations
- // younger than gen from generations gen and older.
- // The parameter clear_perm indicates if the perm_gen's
- // remembered set should also be processed/cleared.
+ // Informs the RS that there are no references to the young generation
+ // from old_gen.
virtual void clear_into_younger(Generation* old_gen) = 0;
// Informs the RS that refs in the given "mr" may have changed
--- a/hotspot/src/share/vm/gc/shared/generation.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/generation.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -80,7 +80,6 @@
// first two fields are word-sized.)
};
-
class Generation: public CHeapObj<mtGC> {
friend class VMStructs;
private:
@@ -299,8 +298,7 @@
// word of "obj" may have been overwritten with a forwarding pointer, and
// also taking care to copy the klass pointer *last*. Returns the new
// object if successful, or else NULL.
- virtual oop par_promote(int thread_num,
- oop obj, markOop m, size_t word_sz);
+ virtual oop par_promote(int thread_num, oop obj, markOop m, size_t word_sz);
// Informs the current generation that all par_promote_alloc's in the
// collection have been completed; any supporting data structures can be
@@ -315,7 +313,7 @@
// This generation will collect all younger generations
// during a full collection.
- virtual bool full_collects_younger_generations() const { return false; }
+ virtual bool full_collects_young_generation() const { return false; }
// This generation does in-place marking, meaning that mark words
// are mutated during the marking phase and presumably reinitialized
@@ -370,18 +368,18 @@
// Some generations may require some cleanup or preparation actions before
// allowing a collection. The default is to do nothing.
- virtual void gc_prologue(bool full) {};
+ virtual void gc_prologue(bool full) {}
// Some generations may require some cleanup actions after a collection.
// The default is to do nothing.
- virtual void gc_epilogue(bool full) {};
+ virtual void gc_epilogue(bool full) {}
// Save the high water marks for the used space in a generation.
- virtual void record_spaces_top() {};
+ virtual void record_spaces_top() {}
// Some generations may need to be "fixed-up" after some allocation
// activity to make them parsable again. The default is to do nothing.
- virtual void ensure_parsability() {};
+ virtual void ensure_parsability() {}
// Time (in ms) when we were last collected or now if a collection is
// in progress.
@@ -417,7 +415,7 @@
virtual void adjust_pointers();
// Mark sweep support phase4
virtual void compact();
- virtual void post_compact() {ShouldNotReachHere();}
+ virtual void post_compact() { ShouldNotReachHere(); }
// Support for CMS's rescan. In this general form we return a pointer
// to an abstract object that can be used, based on specific previously
@@ -432,7 +430,7 @@
// Some generations may require some cleanup actions before allowing
// a verification.
- virtual void prepare_for_verify() {};
+ virtual void prepare_for_verify() {}
// Accessing "marks".
@@ -483,7 +481,7 @@
// Give each generation an opportunity to do clean up for any
// contributed scratch.
- virtual void reset_scratch() {};
+ virtual void reset_scratch() {}
// When an older generation has been collected, and perhaps resized,
// this method will be invoked on all younger generations (from older to
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include <string.h>
+#include "gc/shared/memset_with_concurrent_readers.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+#include "utilities/ostream.hpp"
+
+#if INCLUDE_ALL_GCS
+
+// Unit test
+#ifdef ASSERT
+
+static unsigned line_byte(const char* line, size_t i) {
+ return unsigned(line[i]) & 0xFF;
+}
+
+// Verify memset_with_concurrent_readers mimics memset.
+// We don't attempt to verify the concurrent reader case.
+void test_memset_with_concurrent_readers() {
+ const size_t chunk_size = 8 * BytesPerWord;
+ const unsigned chunk_count = 4;
+ const size_t block_size = (chunk_count + 4) * chunk_size;
+ char block[block_size];
+ char clear_block[block_size];
+ char set_block[block_size];
+
+ // block format:
+ // 0: unused leading chunk
+ // 1: chunk written from start index to end of chunk
+ // ... nchunks fully written chunks
+ // N: chunk written from start of chunk to end index
+ // N+1: unused trailing chunk
+
+ const int clear_value = 0;
+ const int set_value = 0xAC;
+
+ memset(clear_block, clear_value, block_size);
+ memset(set_block, set_value, block_size);
+
+ for (unsigned nchunks = 0; nchunks <= chunk_count; ++nchunks) {
+ for (size_t start = 1; start <= chunk_size; ++start) {
+ for (size_t end = 0; end <= chunk_size; ++end) {
+ size_t set_start = chunk_size + start;
+ size_t set_end = (2 + nchunks) * chunk_size + end;
+ size_t set_size = set_end - set_start;
+
+ memset(block, clear_value, block_size);
+ memset_with_concurrent_readers(&block[set_start], set_value, set_size);
+ bool head_clear = !memcmp(clear_block, block, set_start);
+ bool middle_set = !memcmp(set_block, block + set_start, set_size);
+ bool tail_clear = !memcmp(clear_block, block + set_end, block_size - set_end);
+ if (!(head_clear && middle_set && tail_clear)) {
+ tty->print_cr("*** memset_with_concurrent_readers failed: "
+ "set start " SIZE_FORMAT ", set end " SIZE_FORMAT,
+ set_start, set_end);
+ for (unsigned chunk = 0; chunk < (block_size / chunk_size); ++chunk) {
+ for (unsigned line = 0; line < (chunk_size / BytesPerWord); ++line) {
+ const char* lp = &block[chunk * chunk_size + line * BytesPerWord];
+ tty->print_cr("%d,%d: %2x %2x %2x %2x %2x %2x %2x %2x",
+ chunk, line,
+ line_byte(lp, 0), line_byte(lp, 1),
+ line_byte(lp, 2), line_byte(lp, 3),
+ line_byte(lp, 4), line_byte(lp, 5),
+ line_byte(lp, 6), line_byte(lp, 7));
+ }
+ }
+ assert(head_clear, "leading byte not clear");
+ assert(middle_set, "memset byte not set");
+ assert(tail_clear, "trailing bye not clear");
+ }
+ }
+ }
+ }
+}
+
+#endif // end unit test
+
+#endif // INCLUDE_ALL_GCS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 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 SRC_SHARE_VM_GC_SHARED_MEMSETWITHCONCURRENTREADERS_HPP
+#define SRC_SHARE_VM_GC_SHARED_MEMSETWITHCONCURRENTREADERS_HPP
+
+#include <stddef.h>
+#include <string.h>
+#include "utilities/macros.hpp"
+
+// Only used by concurrent collectors.
+#if INCLUDE_ALL_GCS
+
+// Fill a block of memory with value, like memset, but with the
+// understanding that there may be concurrent readers of that memory.
+void memset_with_concurrent_readers(void* to, int value, size_t size);
+
+#ifdef TARGET_ARCH_sparc
+
+// SPARC requires special handling. See SPARC-specific definition.
+
+#else
+// All others just use memset.
+
+inline void memset_with_concurrent_readers(void* to, int value, size_t size) {
+ ::memset(to, value, size);
+}
+
+#endif // End of target dispatch.
+
+#endif // INCLUDE_ALL_GCS
+
+#endif // include guard
--- a/hotspot/src/share/vm/gc/shared/modRefBarrierSet.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/modRefBarrierSet.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -60,7 +60,6 @@
: BarrierSet(fake_rtti.add_tag(BarrierSet::ModRef)) { }
~ModRefBarrierSet() { }
- virtual void write_ref_field_work(void* field, oop new_val, bool release = false) = 0;
public:
void write_prim_field(HeapWord* field, size_t bytes,
juint val1, juint val2) {}
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -243,10 +243,13 @@
process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
is_alive, keep_alive, complete_gc, task_executor);
- // Process cleaners, but include them in phantom statistics. We expect
- // Cleaner references to be temporary, and don't want to deal with
- // possible incompatibilities arising from making it more visible.
- phantom_count +=
+ }
+
+ // Cleaners
+ size_t cleaner_count = 0;
+ {
+ GCTraceTime tt("Cleaners", trace_time, false, gc_timer, gc_id);
+ cleaner_count =
process_discovered_reflist(_discoveredCleanerRefs, NULL, true,
is_alive, keep_alive, complete_gc, task_executor);
}
@@ -256,15 +259,17 @@
// that is not how the JDK1.2 specification is. See #4126360. Native code can
// thus use JNI weak references to circumvent the phantom references and
// resurrect a "post-mortem" object.
+ size_t jni_weak_ref_count = 0;
{
GCTraceTime tt("JNI Weak Reference", trace_time, false, gc_timer, gc_id);
if (task_executor != NULL) {
task_executor->set_single_threaded_mode();
}
- process_phaseJNI(is_alive, keep_alive, complete_gc);
+ jni_weak_ref_count =
+ process_phaseJNI(is_alive, keep_alive, complete_gc);
}
- return ReferenceProcessorStats(soft_count, weak_count, final_count, phantom_count);
+ return ReferenceProcessorStats(soft_count, weak_count, final_count, phantom_count, cleaner_count, jni_weak_ref_count);
}
#ifndef PRODUCT
@@ -291,17 +296,17 @@
}
#endif
-void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive,
- OopClosure* keep_alive,
- VoidClosure* complete_gc) {
-#ifndef PRODUCT
+size_t ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive,
+ OopClosure* keep_alive,
+ VoidClosure* complete_gc) {
+ DEBUG_ONLY(size_t check_count = count_jni_refs();)
+ size_t count = JNIHandles::weak_oops_do(is_alive, keep_alive);
+ assert(count == check_count, "Counts didn't match");
+ complete_gc->do_void();
if (PrintGCDetails && PrintReferenceGC) {
- unsigned int count = count_jni_refs();
- gclog_or_tty->print(", %u refs", count);
+ gclog_or_tty->print(", " SIZE_FORMAT " refs", count);
}
-#endif
- JNIHandles::weak_oops_do(is_alive, keep_alive);
- complete_gc->do_void();
+ return count;
}
@@ -941,9 +946,10 @@
list = &_discoveredCleanerRefs[id];
break;
case REF_NONE:
+ case REF_JNI:
// we should not reach here if we are an InstanceRefKlass
default:
- ShouldNotReachHere();
+ guarantee(false, err_msg("rt should not be %d", rt));
}
if (TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr("Thread %d gets list " INTPTR_FORMAT, id, p2i(list));
@@ -1059,7 +1065,7 @@
// can mark through them now, rather than delaying that
// to the reference-processing phase. Since all current
// time-stamp policies advance the soft-ref clock only
- // at a major collection cycle, this is always currently
+ // at a full collection cycle, this is always currently
// accurate.
if (!_current_soft_ref_policy->should_clear_reference(obj, _soft_ref_timestamp_clock)) {
return false;
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -247,7 +247,7 @@
DiscoveredList* _discoveredCleanerRefs;
public:
- static int number_of_subclasses_of_ref() { return (REF_CLEANER - REF_OTHER); }
+ static int number_of_subclasses_of_ref() { return REF_LISTS_COUNT; }
uint num_q() { return _num_q; }
uint max_num_q() { return _max_num_q; }
@@ -271,9 +271,9 @@
VoidClosure* complete_gc,
AbstractRefProcTaskExecutor* task_executor);
- void process_phaseJNI(BoolObjectClosure* is_alive,
- OopClosure* keep_alive,
- VoidClosure* complete_gc);
+ size_t process_phaseJNI(BoolObjectClosure* is_alive,
+ OopClosure* keep_alive,
+ VoidClosure* complete_gc);
// Work methods used by the method process_discovered_reflist
// Phase1: keep alive all those referents that are otherwise
--- a/hotspot/src/share/vm/gc/shared/referenceProcessorStats.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessorStats.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -36,22 +36,30 @@
size_t _weak_count;
size_t _final_count;
size_t _phantom_count;
+ size_t _cleaner_count;
+ size_t _jni_weak_ref_count;
public:
ReferenceProcessorStats() :
_soft_count(0),
_weak_count(0),
_final_count(0),
- _phantom_count(0) {}
+ _phantom_count(0),
+ _cleaner_count(0),
+ _jni_weak_ref_count(0) {}
ReferenceProcessorStats(size_t soft_count,
size_t weak_count,
size_t final_count,
- size_t phantom_count) :
+ size_t phantom_count,
+ size_t cleaner_count,
+ size_t jni_weak_ref_count) :
_soft_count(soft_count),
_weak_count(weak_count),
_final_count(final_count),
- _phantom_count(phantom_count)
+ _phantom_count(phantom_count),
+ _cleaner_count(cleaner_count),
+ _jni_weak_ref_count(jni_weak_ref_count)
{}
size_t soft_count() const {
@@ -69,5 +77,13 @@
size_t phantom_count() const {
return _phantom_count;
}
+
+ size_t cleaner_count() const {
+ return _cleaner_count;
+ }
+
+ size_t jni_weak_ref_count() const {
+ return _jni_weak_ref_count;
+ }
};
#endif
--- a/hotspot/src/share/vm/gc/shared/space.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/space.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -237,7 +237,7 @@
HeapWord* bottom, \
HeapWord* top, \
ClosureType* cl) { \
- bottom += oop(bottom)->oop_iterate(cl, mr); \
+ bottom += oop(bottom)->oop_iterate_size(cl, mr); \
if (bottom < top) { \
HeapWord* next_obj = bottom + oop(bottom)->size(); \
while (next_obj < top) { \
@@ -508,7 +508,7 @@
HeapWord* t = mr.end(); \
while (obj_addr < t) { \
assert(oop(obj_addr)->is_oop(), "Should be an oop"); \
- obj_addr += oop(obj_addr)->oop_iterate(blk); \
+ obj_addr += oop(obj_addr)->oop_iterate_size(blk); \
} \
}
@@ -523,7 +523,7 @@
HeapWord* t = top();
// Could call objects iterate, but this is easier.
while (obj_addr < t) {
- obj_addr += oop(obj_addr)->oop_iterate(blk);
+ obj_addr += oop(obj_addr)->oop_iterate_size(blk);
}
}
@@ -578,7 +578,7 @@
Prefetch::write(p, interval); \
debug_only(HeapWord* prev = p); \
oop m = oop(p); \
- p += m->oop_iterate(blk); \
+ p += m->oop_iterate_size(blk); \
} \
} while (t < top()); \
\
--- a/hotspot/src/share/vm/gc/shared/specialized_oop_closures.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/specialized_oop_closures.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -42,6 +42,8 @@
class ScanClosure;
class FastScanClosure;
class FilteringClosure;
+// MarkSweep
+class MarkAndPushClosure;
// ParNew
class ParScanWithBarrierClosure;
class ParScanWithoutBarrierClosure;
@@ -87,6 +89,9 @@
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f) \
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f)
+#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f) \
+ f(MarkAndPushClosure,_nv)
+
#if INCLUDE_ALL_GCS
#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f) \
f(MarkRefsIntoAndScanClosure,_nv) \
@@ -101,10 +106,12 @@
#if INCLUDE_ALL_GCS
#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \
+ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f) \
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f) \
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f)
#else // INCLUDE_ALL_GCS
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)
+#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \
+ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f)
#endif // INCLUDE_ALL_GCS
--- a/hotspot/src/share/vm/gc/shared/taskqueue.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/taskqueue.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -258,8 +258,8 @@
#ifdef ASSERT
bool ObjArrayTask::is_valid() const {
- return _obj != NULL && _obj->is_objArray() && _index > 0 &&
- _index < objArrayOop(_obj)->length();
+ return _obj != NULL && _obj->is_objArray() && _index >= 0 &&
+ _index < objArrayOop(_obj)->length();
}
#endif // ASSERT
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -213,15 +213,18 @@
size_t _size; // size of object to be allocated
Metaspace::MetadataType _mdtype;
ClassLoaderData* _loader_data;
+
public:
VM_CollectForMetadataAllocation(ClassLoaderData* loader_data,
- size_t size, Metaspace::MetadataType mdtype,
+ size_t size,
+ Metaspace::MetadataType mdtype,
uint gc_count_before,
uint full_gc_count_before,
GCCause::Cause gc_cause)
: VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true),
_loader_data(loader_data), _size(size), _mdtype(mdtype), _result(NULL) {
}
+
virtual VMOp_Type type() const { return VMOp_CollectForMetadataAllocation; }
virtual void doit();
MetaWord* result() const { return _result; }
--- a/hotspot/src/share/vm/memory/filemap.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/memory/filemap.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -707,12 +707,16 @@
addr, string_ranges[i].byte_size(), si->_read_only,
si->_allow_exec);
if (base == NULL || base != addr) {
+ // dealloc the string regions from java heap
+ dealloc_string_regions();
fail_continue("Unable to map shared string space at required address.");
return false;
}
}
if (!verify_string_regions()) {
+ // dealloc the string regions from java heap
+ dealloc_string_regions();
fail_continue("Shared string regions are corrupt");
return false;
}
@@ -745,12 +749,14 @@
}
void FileMapInfo::fixup_string_regions() {
+#if INCLUDE_ALL_GCS
// If any string regions were found, call the fill routine to make them parseable.
// Note that string_ranges may be non-NULL even if no ranges were found.
if (num_ranges != 0) {
assert(string_ranges != NULL, "Null string_ranges array with non-zero count");
G1CollectedHeap::heap()->fill_archive_regions(string_ranges, num_ranges);
}
+#endif
}
bool FileMapInfo::verify_region_checksum(int i) {
@@ -793,20 +799,14 @@
}
}
-void FileMapInfo::unmap_string_regions() {
- for (int i = MetaspaceShared::first_string;
- i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
- struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
- size_t used = si->_used;
- if (used > 0) {
- size_t size = align_size_up(used, os::vm_allocation_granularity());
- char* addr = (char*)((void*)oopDesc::decode_heap_oop_not_null(
- (narrowOop)si->_addr._offset));
- if (!os::unmap_memory(addr, size)) {
- fail_stop("Unable to unmap shared space.");
- }
- }
+// dealloc the archived string region from java heap
+void FileMapInfo::dealloc_string_regions() {
+#if INCLUDE_ALL_GCS
+ if (num_ranges > 0) {
+ assert(string_ranges != NULL, "Null string_ranges array with non-zero count");
+ G1CollectedHeap::heap()->dealloc_archive_regions(string_ranges, num_ranges);
}
+#endif
}
void FileMapInfo::assert_mark(bool check) {
@@ -967,7 +967,9 @@
map_info->_header->_space[i]._addr._base = NULL;
}
}
- map_info->unmap_string_regions();
+ // Dealloc the string regions only without unmapping. The string regions are part
+ // of the java heap. Unmapping of the heap regions are managed by GC.
+ map_info->dealloc_string_regions();
} else if (DumpSharedSpaces) {
fail_stop("%s", msg);
}
--- a/hotspot/src/share/vm/memory/filemap.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/memory/filemap.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -208,7 +208,7 @@
bool verify_string_regions();
void fixup_string_regions();
void unmap_region(int i);
- void unmap_string_regions();
+ void dealloc_string_regions();
bool verify_region_checksum(int i);
void close();
bool is_open() { return _file_open; }
--- a/hotspot/src/share/vm/memory/iterator.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/memory/iterator.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -61,7 +61,7 @@
//
// 1) do_klass on the header klass pointer.
// 2) do_klass on the klass pointer in the mirrors.
- // 3) do_class_loader_data on the class loader data in class loaders.
+ // 3) do_cld on the class loader data in class loaders.
//
// The virtual (without suffix) and the non-virtual (with _nv suffix) need
// to be updated together, or else the devirtualization will break.
@@ -71,13 +71,14 @@
// ExtendedOopClosures that don't need to walk the metadata.
// Currently, only CMS and G1 need these.
+ bool do_metadata_nv() { return false; }
virtual bool do_metadata() { return do_metadata_nv(); }
- bool do_metadata_nv() { return false; }
- virtual void do_klass(Klass* k) { do_klass_nv(k); }
- void do_klass_nv(Klass* k) { ShouldNotReachHere(); }
+ void do_klass_nv(Klass* k) { ShouldNotReachHere(); }
+ virtual void do_klass(Klass* k) { do_klass_nv(k); }
- virtual void do_class_loader_data(ClassLoaderData* cld) { ShouldNotReachHere(); }
+ void do_cld_nv(ClassLoaderData* cld) { ShouldNotReachHere(); }
+ virtual void do_cld(ClassLoaderData* cld) { do_cld_nv(cld); }
// True iff this closure may be safely applied more than once to an oop
// location without an intervening "major reset" (like the end of a GC).
@@ -180,13 +181,14 @@
_klass_closure.initialize(this);
}
- virtual bool do_metadata() { return do_metadata_nv(); }
- inline bool do_metadata_nv() { return true; }
+ bool do_metadata_nv() { return true; }
+ virtual bool do_metadata() { return do_metadata_nv(); }
- virtual void do_klass(Klass* k);
void do_klass_nv(Klass* k);
+ virtual void do_klass(Klass* k) { do_klass_nv(k); }
- virtual void do_class_loader_data(ClassLoaderData* cld);
+ void do_cld_nv(ClassLoaderData* cld);
+ virtual void do_cld(ClassLoaderData* cld) { do_cld_nv(cld); }
};
// ObjectClosure is used for iterating through an object space
@@ -370,6 +372,7 @@
public:
template <class OopClosureType, typename T> static void do_oop(OopClosureType* closure, T* p);
template <class OopClosureType> static void do_klass(OopClosureType* closure, Klass* k);
+ template <class OopClosureType> static void do_cld(OopClosureType* closure, ClassLoaderData* cld);
template <class OopClosureType> static bool do_metadata(OopClosureType* closure);
};
@@ -378,6 +381,7 @@
public:
template <class OopClosureType, typename T> static void do_oop(OopClosureType* closure, T* p);
template <class OopClosureType> static void do_klass(OopClosureType* closure, Klass* k);
+ template <class OopClosureType> static void do_cld(OopClosureType* closure, ClassLoaderData* cld);
template <class OopClosureType> static bool do_metadata(OopClosureType* closure);
};
--- a/hotspot/src/share/vm/memory/iterator.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/memory/iterator.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -36,7 +36,7 @@
#include "oops/typeArrayKlass.inline.hpp"
#include "utilities/debug.hpp"
-inline void MetadataAwareOopClosure::do_class_loader_data(ClassLoaderData* cld) {
+inline void MetadataAwareOopClosure::do_cld_nv(ClassLoaderData* cld) {
assert(_klass_closure._oop_closure == this, "Must be");
bool claim = true; // Must claim the class loader data before processing.
@@ -45,11 +45,9 @@
inline void MetadataAwareOopClosure::do_klass_nv(Klass* k) {
ClassLoaderData* cld = k->class_loader_data();
- do_class_loader_data(cld);
+ do_cld_nv(cld);
}
-inline void MetadataAwareOopClosure::do_klass(Klass* k) { do_klass_nv(k); }
-
#ifdef ASSERT
// This verification is applied to all visited oops.
// The closures can turn is off by overriding should_verify_oops().
@@ -78,6 +76,10 @@
closure->do_klass_nv(k);
}
template <class OopClosureType>
+void Devirtualizer<true>::do_cld(OopClosureType* closure, ClassLoaderData* cld) {
+ closure->do_cld_nv(cld);
+}
+template <class OopClosureType>
inline bool Devirtualizer<true>::do_metadata(OopClosureType* closure) {
// Make sure the non-virtual and the virtual versions match.
assert(closure->do_metadata_nv() == closure->do_metadata(), "Inconsistency in do_metadata");
@@ -96,6 +98,10 @@
closure->do_klass(k);
}
template <class OopClosureType>
+void Devirtualizer<false>::do_cld(OopClosureType* closure, ClassLoaderData* cld) {
+ closure->do_cld(cld);
+}
+template <class OopClosureType>
bool Devirtualizer<false>::do_metadata(OopClosureType* closure) {
return closure->do_metadata();
}
--- a/hotspot/src/share/vm/memory/referenceType.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/memory/referenceType.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -32,11 +32,15 @@
enum ReferenceType {
REF_NONE, // Regular class
REF_OTHER, // Subclass of java/lang/ref/Reference, but not subclass of one of the classes below
+ ///////////////// Only the types below have their own discovered lists
REF_SOFT, // Subclass of java/lang/ref/SoftReference
REF_WEAK, // Subclass of java/lang/ref/WeakReference
REF_FINAL, // Subclass of java/lang/ref/FinalReference
REF_PHANTOM, // Subclass of java/lang/ref/PhantomReference
- REF_CLEANER // Subclass of sun/misc/Cleaner
+ REF_CLEANER, // Subclass of sun/misc/Cleaner
+ ///////////////// Only the types in the above range have their own discovered lists
+ REF_JNI, // JNI weak refs
+ REF_LISTS_COUNT = REF_CLEANER - REF_OTHER // Number of discovered lists
};
#endif // SHARE_VM_MEMORY_REFERENCETYPE_HPP
--- a/hotspot/src/share/vm/oops/arrayKlass.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/arrayKlass.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -147,30 +147,30 @@
// Array oop iteration macros for declarations.
// Used to generate the declarations in the *ArrayKlass header files.
-#define OOP_OOP_ITERATE_DECL_RANGE(OopClosureType, nv_suffix) \
- int oop_oop_iterate_range##nv_suffix(oop obj, OopClosureType* closure, int start, int end);
+#define OOP_OOP_ITERATE_DECL_RANGE(OopClosureType, nv_suffix) \
+ void oop_oop_iterate_range##nv_suffix(oop obj, OopClosureType* closure, int start, int end);
#if INCLUDE_ALL_GCS
// Named NO_BACKWARDS because the definition used by *ArrayKlass isn't reversed, see below.
-#define OOP_OOP_ITERATE_DECL_NO_BACKWARDS(OopClosureType, nv_suffix) \
- int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure);
+#define OOP_OOP_ITERATE_DECL_NO_BACKWARDS(OopClosureType, nv_suffix) \
+ void oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure);
#endif // INCLUDE_ALL_GCS
// Array oop iteration macros for definitions.
// Used to generate the definitions in the *ArrayKlass.inline.hpp files.
-#define OOP_OOP_ITERATE_DEFN_RANGE(KlassType, OopClosureType, nv_suffix) \
- \
-int KlassType::oop_oop_iterate_range##nv_suffix(oop obj, OopClosureType* closure, int start, int end) { \
- return oop_oop_iterate_range<nvs_to_bool(nv_suffix)>(obj, closure, start, end); \
+#define OOP_OOP_ITERATE_DEFN_RANGE(KlassType, OopClosureType, nv_suffix) \
+ \
+void KlassType::oop_oop_iterate_range##nv_suffix(oop obj, OopClosureType* closure, int start, int end) { \
+ oop_oop_iterate_range<nvs_to_bool(nv_suffix)>(obj, closure, start, end); \
}
#if INCLUDE_ALL_GCS
-#define OOP_OOP_ITERATE_DEFN_NO_BACKWARDS(KlassType, OopClosureType, nv_suffix) \
-int KlassType::oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
- /* No reverse implementation ATM. */ \
- return oop_oop_iterate<nvs_to_bool(nv_suffix)>(obj, closure); \
+#define OOP_OOP_ITERATE_DEFN_NO_BACKWARDS(KlassType, OopClosureType, nv_suffix) \
+void KlassType::oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
+ /* No reverse implementation ATM. */ \
+ oop_oop_iterate<nvs_to_bool(nv_suffix)>(obj, closure); \
}
#else
#define OOP_OOP_ITERATE_DEFN_NO_BACKWARDS(KlassType, OopClosureType, nv_suffix)
--- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -51,7 +51,6 @@
// GC specific object visitors
//
// Mark Sweep
- void oop_ms_follow_contents(oop obj);
int oop_ms_adjust_pointers(oop obj);
#if INCLUDE_ALL_GCS
// Parallel Scavenge
@@ -71,19 +70,19 @@
// Forward iteration
// Iterate over the oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate(oop obj, OopClosureType* closure);
+ inline void oop_oop_iterate(oop obj, OopClosureType* closure);
#if INCLUDE_ALL_GCS
// Reverse iteration
// Iterate over the oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
+ inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
#endif
// Bounded range iteration
// Iterate over the oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
+ inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
public:
--- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -26,6 +26,7 @@
#define SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_INLINE_HPP
#include "classfile/javaClasses.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/instanceClassLoaderKlass.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/oop.inline.hpp"
@@ -34,48 +35,42 @@
#include "utilities/macros.hpp"
template <bool nv, class OopClosureType>
-inline int InstanceClassLoaderKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
- int size = InstanceKlass::oop_oop_iterate<nv>(obj, closure);
+inline void InstanceClassLoaderKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
+ InstanceKlass::oop_oop_iterate<nv>(obj, closure);
if (Devirtualizer<nv>::do_metadata(closure)) {
ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);
// cld can be null if we have a non-registered class loader.
if (cld != NULL) {
- closure->do_class_loader_data(cld);
+ Devirtualizer<nv>::do_cld(closure, cld);
}
}
-
- return size;
}
#if INCLUDE_ALL_GCS
template <bool nv, class OopClosureType>
-inline int InstanceClassLoaderKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
- int size = InstanceKlass::oop_oop_iterate_reverse<nv>(obj, closure);
+inline void InstanceClassLoaderKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
+ InstanceKlass::oop_oop_iterate_reverse<nv>(obj, closure);
assert(!Devirtualizer<nv>::do_metadata(closure),
"Code to handle metadata is not implemented");
-
- return size;
}
#endif // INCLUDE_ALL_GCS
template <bool nv, class OopClosureType>
-inline int InstanceClassLoaderKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- int size = InstanceKlass::oop_oop_iterate_bounded<nv>(obj, closure, mr);
+inline void InstanceClassLoaderKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ InstanceKlass::oop_oop_iterate_bounded<nv>(obj, closure, mr);
if (Devirtualizer<nv>::do_metadata(closure)) {
if (mr.contains(obj)) {
ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);
// cld can be null if we have a non-registered class loader.
if (cld != NULL) {
- closure->do_class_loader_data(cld);
+ Devirtualizer<nv>::do_cld(closure, cld);
}
}
}
-
- return size;
}
#define ALL_INSTANCE_CLASS_LOADER_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -1014,7 +1014,6 @@
// GC specific object visitors
//
// Mark Sweep
- void oop_ms_follow_contents(oop obj);
int oop_ms_adjust_pointers(oop obj);
#if INCLUDE_ALL_GCS
// Parallel Scavenge
--- a/hotspot/src/share/vm/oops/instanceKlass.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -38,6 +38,8 @@
// as the previous macro based implementation.
#ifdef TARGET_COMPILER_visCPP
#define INLINE __forceinline
+#elif defined(TARGET_COMPILER_sparcWorks)
+#define INLINE __attribute__((always_inline))
#else
#define INLINE inline
#endif
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -91,7 +91,6 @@
// GC specific object visitors
//
// Mark Sweep
- void oop_ms_follow_contents(oop obj);
int oop_ms_adjust_pointers(oop obj);
#if INCLUDE_ALL_GCS
// Parallel Scavenge
@@ -121,21 +120,21 @@
// Forward iteration
// Iterate over the oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate(oop obj, OopClosureType* closure);
+ inline void oop_oop_iterate(oop obj, OopClosureType* closure);
// Reverse iteration
#if INCLUDE_ALL_GCS
// Iterate over the oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
+ inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
#endif
// Bounded range iteration
// Iterate over the oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
+ inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
// Iterate over the static fields.
template <bool nv, class OopClosureType>
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -53,30 +53,40 @@
}
template <bool nv, class OopClosureType>
-int InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
+void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
InstanceKlass::oop_oop_iterate<nv>(obj, closure);
if (Devirtualizer<nv>::do_metadata(closure)) {
Klass* klass = java_lang_Class::as_Klass(obj);
// We'll get NULL for primitive mirrors.
if (klass != NULL) {
- Devirtualizer<nv>::do_klass(closure, klass);
+ if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
+ // An anonymous class doesn't have its own class loader, so when handling
+ // the java mirror for an anonymous class we need to make sure its class
+ // loader data is claimed, this is done by calling do_cld explicitly.
+ // For non-anonymous classes the call to do_cld is made when the class
+ // loader itself is handled.
+ Devirtualizer<nv>::do_cld(closure, klass->class_loader_data());
+ } else {
+ Devirtualizer<nv>::do_klass(closure, klass);
+ }
+ } else {
+ // If klass is NULL then this a mirror for a primitive type.
+ // We don't have to follow them, since they are handled as strong
+ // roots in Universe::oops_do.
+ assert(java_lang_Class::is_primitive(obj), "Sanity check");
}
}
oop_oop_iterate_statics<nv>(obj, closure);
-
- return oop_size(obj);
}
#if INCLUDE_ALL_GCS
template <bool nv, class OopClosureType>
-int InstanceMirrorKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
+void InstanceMirrorKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
InstanceKlass::oop_oop_iterate_reverse<nv>(obj, closure);
InstanceMirrorKlass::oop_oop_iterate_statics<nv>(obj, closure);
-
- return oop_size(obj);
}
#endif
@@ -115,7 +125,7 @@
}
template <bool nv, class OopClosureType>
-int InstanceMirrorKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+void InstanceMirrorKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
InstanceKlass::oop_oop_iterate_bounded<nv>(obj, closure, mr);
if (Devirtualizer<nv>::do_metadata(closure)) {
@@ -129,8 +139,6 @@
}
oop_oop_iterate_statics_bounded<nv>(obj, closure, mr);
-
- return oop_size(obj);
}
#define ALL_INSTANCE_MIRROR_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
--- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -67,7 +67,6 @@
// GC specific object visitors
//
// Mark Sweep
- void oop_ms_follow_contents(oop obj);
int oop_ms_adjust_pointers(oop obj);
#if INCLUDE_ALL_GCS
// Parallel Scavenge
@@ -88,19 +87,19 @@
private:
// Iterate over all oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate(oop obj, OopClosureType* closure);
+ inline void oop_oop_iterate(oop obj, OopClosureType* closure);
// Reverse iteration
#if INCLUDE_ALL_GCS
// Iterate over all oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
+ inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
#endif // INCLUDE_ALL_GCS
// Bounded range iteration
// Iterate over all oop fields and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
+ inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
// Reference processing part of the iterators.
--- a/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -106,37 +106,27 @@
}
template <bool nv, class OopClosureType>
-int InstanceRefKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
- // Get size before changing pointers
- int size = InstanceKlass::oop_oop_iterate<nv>(obj, closure);
+void InstanceRefKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
+ InstanceKlass::oop_oop_iterate<nv>(obj, closure);
oop_oop_iterate_ref_processing<nv>(obj, closure);
-
- return size;
}
#if INCLUDE_ALL_GCS
template <bool nv, class OopClosureType>
-int InstanceRefKlass::
-oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
- // Get size before changing pointers
- int size = InstanceKlass::oop_oop_iterate_reverse<nv>(obj, closure);
+void InstanceRefKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
+ InstanceKlass::oop_oop_iterate_reverse<nv>(obj, closure);
oop_oop_iterate_ref_processing<nv>(obj, closure);
-
- return size;
}
#endif // INCLUDE_ALL_GCS
template <bool nv, class OopClosureType>
-int InstanceRefKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- // Get size before changing pointers
- int size = InstanceKlass::oop_oop_iterate_bounded<nv>(obj, closure, mr);
+void InstanceRefKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ InstanceKlass::oop_oop_iterate_bounded<nv>(obj, closure, mr);
oop_oop_iterate_ref_processing_bounded<nv>(obj, closure, mr);
-
- return size;
}
// Macro to define InstanceRefKlass::oop_oop_iterate for virtual/nonvirtual for
--- a/hotspot/src/share/vm/oops/klass.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/klass.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -572,7 +572,6 @@
// GC specific object visitors
//
// Mark Sweep
- virtual void oop_ms_follow_contents(oop obj) = 0;
virtual int oop_ms_adjust_pointers(oop obj) = 0;
#if INCLUDE_ALL_GCS
// Parallel Scavenge
@@ -584,17 +583,17 @@
// Iterators specialized to particular subtypes
// of ExtendedOopClosure, to avoid closure virtual calls.
-#define Klass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
- virtual int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) = 0; \
- /* Iterates "closure" over all the oops in "obj" (of type "this") within "mr". */ \
- virtual int oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr) = 0;
+#define Klass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
+ virtual void oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) = 0; \
+ /* Iterates "closure" over all the oops in "obj" (of type "this") within "mr". */ \
+ virtual void oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr) = 0;
ALL_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL)
#if INCLUDE_ALL_GCS
-#define Klass_OOP_OOP_ITERATE_DECL_BACKWARDS(OopClosureType, nv_suffix) \
- virtual int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) = 0;
+#define Klass_OOP_OOP_ITERATE_DECL_BACKWARDS(OopClosureType, nv_suffix) \
+ virtual void oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) = 0;
ALL_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL_BACKWARDS)
ALL_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL_BACKWARDS)
@@ -661,35 +660,35 @@
// Used to generate declarations in the *Klass header files.
#define OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
- int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure); \
- int oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr);
+ void oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure); \
+ void oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr);
#if INCLUDE_ALL_GCS
-#define OOP_OOP_ITERATE_DECL_BACKWARDS(OopClosureType, nv_suffix) \
- int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure);
+#define OOP_OOP_ITERATE_DECL_BACKWARDS(OopClosureType, nv_suffix) \
+ void oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure);
#endif // INCLUDE_ALL_GCS
// Oop iteration macros for definitions.
// Used to generate definitions in the *Klass.inline.hpp files.
-#define OOP_OOP_ITERATE_DEFN(KlassType, OopClosureType, nv_suffix) \
-int KlassType::oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
- return oop_oop_iterate<nvs_to_bool(nv_suffix)>(obj, closure); \
+#define OOP_OOP_ITERATE_DEFN(KlassType, OopClosureType, nv_suffix) \
+void KlassType::oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
+ oop_oop_iterate<nvs_to_bool(nv_suffix)>(obj, closure); \
}
#if INCLUDE_ALL_GCS
-#define OOP_OOP_ITERATE_DEFN_BACKWARDS(KlassType, OopClosureType, nv_suffix) \
-int KlassType::oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
- return oop_oop_iterate_reverse<nvs_to_bool(nv_suffix)>(obj, closure); \
+#define OOP_OOP_ITERATE_DEFN_BACKWARDS(KlassType, OopClosureType, nv_suffix) \
+void KlassType::oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
+ oop_oop_iterate_reverse<nvs_to_bool(nv_suffix)>(obj, closure); \
}
#else
#define OOP_OOP_ITERATE_DEFN_BACKWARDS(KlassType, OopClosureType, nv_suffix)
#endif
-#define OOP_OOP_ITERATE_DEFN_BOUNDED(KlassType, OopClosureType, nv_suffix) \
-int KlassType::oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr) { \
- return oop_oop_iterate_bounded<nvs_to_bool(nv_suffix)>(obj, closure, mr); \
+#define OOP_OOP_ITERATE_DEFN_BOUNDED(KlassType, OopClosureType, nv_suffix) \
+void KlassType::oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr) { \
+ oop_oop_iterate_bounded<nvs_to_bool(nv_suffix)>(obj, closure, mr); \
}
#endif // SHARE_VM_OOPS_KLASS_HPP
--- a/hotspot/src/share/vm/oops/objArrayKlass.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -105,7 +105,6 @@
// GC specific object visitors
//
// Mark Sweep
- void oop_ms_follow_contents(oop obj);
int oop_ms_adjust_pointers(oop obj);
#if INCLUDE_ALL_GCS
// Parallel Scavenge
@@ -125,15 +124,15 @@
// Iterate over oop elements and metadata.
template <bool nv, typename OopClosureType>
- inline int oop_oop_iterate(oop obj, OopClosureType* closure);
+ inline void oop_oop_iterate(oop obj, OopClosureType* closure);
// Iterate over oop elements within mr, and metadata.
template <bool nv, typename OopClosureType>
- inline int oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
+ inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
// Iterate over oop elements with indices within [start, end), and metadata.
template <bool nv, class OopClosureType>
- inline int oop_oop_iterate_range(oop obj, OopClosureType* closure, int start, int end);
+ inline void oop_oop_iterate_range(oop obj, OopClosureType* closure, int start, int end);
// Iterate over oop elements within [start, end), and metadata.
// Specialized for [T = oop] or [T = narrowOop].
--- a/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -85,46 +85,31 @@
}
template <bool nv, typename OopClosureType>
-int ObjArrayKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
+void ObjArrayKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
assert (obj->is_array(), "obj must be array");
objArrayOop a = objArrayOop(obj);
- // Get size before changing pointers.
- // Don't call size() or oop_size() since that is a virtual call.
- int size = a->object_size();
if (Devirtualizer<nv>::do_metadata(closure)) {
Devirtualizer<nv>::do_klass(closure, obj->klass());
}
oop_oop_iterate_elements<nv>(a, closure);
-
- return size;
}
template <bool nv, typename OopClosureType>
-int ObjArrayKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+void ObjArrayKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
assert(obj->is_array(), "obj must be array");
objArrayOop a = objArrayOop(obj);
- // Get size before changing pointers.
- // Don't call size() or oop_size() since that is a virtual call
- int size = a->object_size();
-
if (Devirtualizer<nv>::do_metadata(closure)) {
Devirtualizer<nv>::do_klass(closure, a->klass());
}
oop_oop_iterate_elements_bounded<nv>(a, closure, mr);
-
- return size;
}
template <bool nv, typename T, class OopClosureType>
void ObjArrayKlass::oop_oop_iterate_range_specialized(objArrayOop a, OopClosureType* closure, int start, int end) {
- if (Devirtualizer<nv>::do_metadata(closure)) {
- Devirtualizer<nv>::do_klass(closure, a->klass());
- }
-
T* low = start == 0 ? cast_from_oop<T*>(a) : a->obj_at_addr<T>(start);
T* high = (T*)a->base() + end;
@@ -134,21 +119,15 @@
// Like oop_oop_iterate but only iterates over a specified range and only used
// for objArrayOops.
template <bool nv, class OopClosureType>
-int ObjArrayKlass::oop_oop_iterate_range(oop obj, OopClosureType* closure, int start, int end) {
+void ObjArrayKlass::oop_oop_iterate_range(oop obj, OopClosureType* closure, int start, int end) {
assert(obj->is_array(), "obj must be array");
objArrayOop a = objArrayOop(obj);
- // Get size before changing pointers.
- // Don't call size() or oop_size() since that is a virtual call
- int size = a->object_size();
-
if (UseCompressedOops) {
oop_oop_iterate_range_specialized<nv, narrowOop>(a, closure, start, end);
} else {
oop_oop_iterate_range_specialized<nv, oop>(a, closure, start, end);
}
-
- return size;
}
#define ALL_OBJ_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
--- a/hotspot/src/share/vm/oops/objArrayOop.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/objArrayOop.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -46,8 +46,8 @@
#define ObjArrayOop_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
\
-int objArrayOopDesc::oop_iterate_range(OopClosureType* blk, int start, int end) { \
- return ((ObjArrayKlass*)klass())->oop_oop_iterate_range##nv_suffix(this, blk, start, end); \
+void objArrayOopDesc::oop_iterate_range(OopClosureType* blk, int start, int end) { \
+ ((ObjArrayKlass*)klass())->oop_oop_iterate_range##nv_suffix(this, blk, start, end); \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayOop_OOP_ITERATE_DEFN)
--- a/hotspot/src/share/vm/oops/objArrayOop.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/objArrayOop.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -106,7 +106,7 @@
// special iterators for index ranges, returns size of object
#define ObjArrayOop_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
- int oop_iterate_range(OopClosureType* blk, int start, int end);
+ void oop_iterate_range(OopClosureType* blk, int start, int end);
ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayOop_OOP_ITERATE_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayOop_OOP_ITERATE_DECL)
--- a/hotspot/src/share/vm/oops/oop.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/oop.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -330,7 +330,6 @@
// Garbage Collection support
// Mark Sweep
- void ms_follow_contents();
// Adjust all pointers in this object to point at it's forwarded location and
// return the size of this oop. This is used by the MarkSweep collector.
int ms_adjust_pointers();
@@ -344,17 +343,25 @@
// iterators, returns size of object
-#define OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
- int oop_iterate(OopClosureType* blk); \
- int oop_iterate(OopClosureType* blk, MemRegion mr); // Only in mr.
+#define OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
+ void oop_iterate(OopClosureType* blk); \
+ void oop_iterate(OopClosureType* blk, MemRegion mr); // Only in mr.
ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DECL)
+#define OOP_ITERATE_SIZE_DECL(OopClosureType, nv_suffix) \
+ int oop_iterate_size(OopClosureType* blk); \
+ int oop_iterate_size(OopClosureType* blk, MemRegion mr); // Only in mr.
+
+ ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_SIZE_DECL)
+ ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_SIZE_DECL)
+
+
#if INCLUDE_ALL_GCS
-#define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
- int oop_iterate_backwards(OopClosureType* blk);
+#define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
+ void oop_iterate_backwards(OopClosureType* blk);
ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DECL)
--- a/hotspot/src/share/vm/oops/oop.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -695,10 +695,6 @@
}
}
-inline void oopDesc::ms_follow_contents() {
- klass()->oop_ms_follow_contents(this);
-}
-
inline int oopDesc::ms_adjust_pointers() {
debug_only(int check_size = size());
int s = klass()->oop_ms_adjust_pointers(this);
@@ -730,34 +726,50 @@
}
#endif
-#define OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- \
-inline int oopDesc::oop_iterate(OopClosureType* blk) { \
- return klass()->oop_oop_iterate##nv_suffix(this, blk); \
-} \
- \
-inline int oopDesc::oop_iterate(OopClosureType* blk, MemRegion mr) { \
- return klass()->oop_oop_iterate_bounded##nv_suffix(this, blk, mr); \
+#define OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
+ \
+inline void oopDesc::oop_iterate(OopClosureType* blk) { \
+ klass()->oop_oop_iterate##nv_suffix(this, blk); \
+} \
+ \
+inline void oopDesc::oop_iterate(OopClosureType* blk, MemRegion mr) { \
+ klass()->oop_oop_iterate_bounded##nv_suffix(this, blk, mr); \
}
+#define OOP_ITERATE_SIZE_DEFN(OopClosureType, nv_suffix) \
+ \
+inline int oopDesc::oop_iterate_size(OopClosureType* blk) { \
+ Klass* k = klass(); \
+ int size = size_given_klass(k); \
+ k->oop_oop_iterate##nv_suffix(this, blk); \
+ return size; \
+} \
+ \
+inline int oopDesc::oop_iterate_size(OopClosureType* blk, \
+ MemRegion mr) { \
+ Klass* k = klass(); \
+ int size = size_given_klass(k); \
+ k->oop_oop_iterate_bounded##nv_suffix(this, blk, mr); \
+ return size; \
+}
inline int oopDesc::oop_iterate_no_header(OopClosure* blk) {
// The NoHeaderExtendedOopClosure wraps the OopClosure and proxies all
// the do_oop calls, but turns off all other features in ExtendedOopClosure.
NoHeaderExtendedOopClosure cl(blk);
- return oop_iterate(&cl);
+ return oop_iterate_size(&cl);
}
inline int oopDesc::oop_iterate_no_header(OopClosure* blk, MemRegion mr) {
NoHeaderExtendedOopClosure cl(blk);
- return oop_iterate(&cl, mr);
+ return oop_iterate_size(&cl, mr);
}
#if INCLUDE_ALL_GCS
#define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
\
-inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) { \
- return klass()->oop_oop_iterate_backwards##nv_suffix(this, blk); \
+inline void oopDesc::oop_iterate_backwards(OopClosureType* blk) { \
+ klass()->oop_oop_iterate_backwards##nv_suffix(this, blk); \
}
#else
#define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix)
@@ -765,6 +777,7 @@
#define ALL_OOPDESC_OOP_ITERATE(OopClosureType, nv_suffix) \
OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
+ OOP_ITERATE_SIZE_DEFN(OopClosureType, nv_suffix) \
OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix)
ALL_OOP_OOP_ITERATE_CLOSURES_1(ALL_OOPDESC_OOP_ITERATE)
--- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -75,7 +75,6 @@
// GC specific object visitors
//
// Mark Sweep
- void oop_ms_follow_contents(oop obj);
int oop_ms_adjust_pointers(oop obj);
#if INCLUDE_ALL_GCS
// Parallel Scavenge
@@ -90,15 +89,15 @@
private:
// The implementation used by all oop_oop_iterate functions in TypeArrayKlasses.
- inline int oop_oop_iterate_impl(oop obj, ExtendedOopClosure* closure);
+ inline void oop_oop_iterate_impl(oop obj, ExtendedOopClosure* closure);
// Wraps oop_oop_iterate_impl to conform to macros.
template <bool nv, typename OopClosureType>
- inline int oop_oop_iterate(oop obj, OopClosureType* closure);
+ inline void oop_oop_iterate(oop obj, OopClosureType* closure);
// Wraps oop_oop_iterate_impl to conform to macros.
template <bool nv, typename OopClosureType>
- inline int oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
+ inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
public:
--- a/hotspot/src/share/vm/oops/typeArrayKlass.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -33,22 +33,20 @@
class ExtendedOopClosure;
-inline int TypeArrayKlass::oop_oop_iterate_impl(oop obj, ExtendedOopClosure* closure) {
+inline void TypeArrayKlass::oop_oop_iterate_impl(oop obj, ExtendedOopClosure* closure) {
assert(obj->is_typeArray(),"must be a type array");
- typeArrayOop t = typeArrayOop(obj);
// Performance tweak: We skip iterating over the klass pointer since we
// know that Universe::TypeArrayKlass never moves.
- return t->object_size();
}
template <bool nv, typename OopClosureType>
-int TypeArrayKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
- return oop_oop_iterate_impl(obj, closure);
+void TypeArrayKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
+ oop_oop_iterate_impl(obj, closure);
}
template <bool nv, typename OopClosureType>
-int TypeArrayKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- return oop_oop_iterate_impl(obj, closure);
+void TypeArrayKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ oop_oop_iterate_impl(obj, closure);
}
#define ALL_TYPE_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
--- a/hotspot/src/share/vm/opto/arraycopynode.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/arraycopynode.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -681,10 +681,10 @@
uint header = arrayOopDesc::base_offset_in_bytes(ary_elem);
uint elemsize = type2aelembytes(ary_elem);
- intptr_t dest_pos_plus_len_lo = (((intptr_t)dest_pos_t->_lo) + len_t->_lo) * elemsize + header;
- intptr_t dest_pos_plus_len_hi = (((intptr_t)dest_pos_t->_hi) + len_t->_hi) * elemsize + header;
- intptr_t dest_pos_lo = ((intptr_t)dest_pos_t->_lo) * elemsize + header;
- intptr_t dest_pos_hi = ((intptr_t)dest_pos_t->_hi) * elemsize + header;
+ jlong dest_pos_plus_len_lo = (((jlong)dest_pos_t->_lo) + len_t->_lo) * elemsize + header;
+ jlong dest_pos_plus_len_hi = (((jlong)dest_pos_t->_hi) + len_t->_hi) * elemsize + header;
+ jlong dest_pos_lo = ((jlong)dest_pos_t->_lo) * elemsize + header;
+ jlong dest_pos_hi = ((jlong)dest_pos_t->_hi) * elemsize + header;
if (must_modify) {
if (offset_lo >= dest_pos_hi && offset_hi < dest_pos_plus_len_lo) {
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -419,6 +419,8 @@
case vmIntrinsics::_updateByteBufferCRC32:
case vmIntrinsics::_updateBytesCRC32C:
case vmIntrinsics::_updateDirectByteBufferCRC32C:
+ case vmIntrinsics::_updateBytesAdler32:
+ case vmIntrinsics::_updateByteBufferAdler32:
case vmIntrinsics::_profileBoolean:
case vmIntrinsics::_isCompileConstant:
break;
--- a/hotspot/src/share/vm/opto/classes.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/classes.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -290,6 +290,7 @@
macro(MulReductionVD)
macro(DivVF)
macro(DivVD)
+macro(SqrtVD)
macro(LShiftCntV)
macro(RShiftCntV)
macro(LShiftVB)
--- a/hotspot/src/share/vm/opto/compile.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/compile.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -523,7 +523,7 @@
void print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
stringStream ss;
- CompileTask::print_inlining(&ss, method, inline_level, bci, msg);
+ CompileTask::print_inlining_inner(&ss, method, inline_level, bci, msg);
print_inlining_stream()->print("%s", ss.as_string());
}
--- a/hotspot/src/share/vm/opto/doCall.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/doCall.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -49,7 +49,7 @@
method->print_short_name();
tty->cr();
}
- CompileTask::print_inlining(prof_method, depth, bci);
+ CompileTask::print_inlining_tty(prof_method, depth, bci);
} else {
out = C->print_inlining_stream();
}
--- a/hotspot/src/share/vm/opto/escape.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/escape.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -963,6 +963,7 @@
strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ||
strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32") == 0 ||
strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32C") == 0 ||
+ strcmp(call->as_CallLeaf()->_name, "updateBytesAdler32") == 0 ||
strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 ||
strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
@@ -3241,7 +3242,7 @@
// Note 2: MergeMem may already contains instance memory slices added
// during find_inst_mem() call when memory nodes were processed above.
igvn->hash_delete(nmm);
- uint nslices = nmm->req();
+ uint nslices = MIN2(nmm->req(), new_index_start);
for (uint i = Compile::AliasIdxRaw+1; i < nslices; i++) {
Node* mem = nmm->in(i);
Node* cur = NULL;
--- a/hotspot/src/share/vm/opto/graphKit.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1522,7 +1522,7 @@
g1_write_barrier_pre(do_load, obj, adr, adr_idx, val, val_type, pre_val, bt);
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
case BarrierSet::ModRef:
break;
@@ -1539,7 +1539,7 @@
case BarrierSet::G1SATBCTLogging:
return true; // Can move it if no safepoint
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
case BarrierSet::ModRef:
return true; // There is no pre-barrier
@@ -1565,7 +1565,7 @@
g1_write_barrier_post(store, obj, adr, adr_idx, val, bt, use_precise);
break;
- case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
write_barrier_post(store, obj, adr, adr_idx, val, use_precise);
break;
@@ -3791,7 +3791,7 @@
Node* cast = __ CastPX(__ ctrl(), adr);
// Divide by card size
- assert(Universe::heap()->barrier_set()->kind() == BarrierSet::CardTableModRef,
+ assert(Universe::heap()->barrier_set()->is_a(BarrierSet::CardTableModRef),
"Only one we handle so far.");
Node* card_offset = __ URShiftX( cast, __ ConI(CardTableModRefBS::card_shift) );
--- a/hotspot/src/share/vm/opto/library_call.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/library_call.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -296,6 +296,8 @@
Node* get_table_from_crc32c_class(ciInstanceKlass *crc32c_class);
bool inline_updateBytesCRC32C();
bool inline_updateDirectByteBufferCRC32C();
+ bool inline_updateBytesAdler32();
+ bool inline_updateByteBufferAdler32();
bool inline_multiplyToLen();
bool inline_squareToLen();
bool inline_mulAdd();
@@ -699,6 +701,11 @@
case vmIntrinsics::_updateDirectByteBufferCRC32C:
return inline_updateDirectByteBufferCRC32C();
+ case vmIntrinsics::_updateBytesAdler32:
+ return inline_updateBytesAdler32();
+ case vmIntrinsics::_updateByteBufferAdler32:
+ return inline_updateByteBufferAdler32();
+
case vmIntrinsics::_profileBoolean:
return inline_profileBoolean();
case vmIntrinsics::_isCompileConstant:
@@ -5547,6 +5554,87 @@
return true;
}
+//------------------------------inline_updateBytesAdler32----------------------
+//
+// Calculate Adler32 checksum for byte[] array.
+// int java.util.zip.Adler32.updateBytes(int crc, byte[] buf, int off, int len)
+//
+bool LibraryCallKit::inline_updateBytesAdler32() {
+ assert(UseAdler32Intrinsics, "Adler32 Instrinsic support need"); // check if we actually need to check this flag or check a different one
+ assert(callee()->signature()->size() == 4, "updateBytes has 4 parameters");
+ assert(callee()->holder()->is_loaded(), "Adler32 class must be loaded");
+ // no receiver since it is static method
+ Node* crc = argument(0); // type: int
+ Node* src = argument(1); // type: oop
+ Node* offset = argument(2); // type: int
+ Node* length = argument(3); // type: int
+
+ const Type* src_type = src->Value(&_gvn);
+ const TypeAryPtr* top_src = src_type->isa_aryptr();
+ if (top_src == NULL || top_src->klass() == NULL) {
+ // failed array check
+ return false;
+ }
+
+ // Figure out the size and type of the elements we will be copying.
+ BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+ if (src_elem != T_BYTE) {
+ return false;
+ }
+
+ // 'src_start' points to src array + scaled offset
+ Node* src_start = array_element_address(src, offset, src_elem);
+
+ // We assume that range check is done by caller.
+ // TODO: generate range check (offset+length < src.length) in debug VM.
+
+ // Call the stub.
+ address stubAddr = StubRoutines::updateBytesAdler32();
+ const char *stubName = "updateBytesAdler32";
+
+ Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesAdler32_Type(),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ crc, src_start, length);
+ Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
+ set_result(result);
+ return true;
+}
+
+//------------------------------inline_updateByteBufferAdler32---------------
+//
+// Calculate Adler32 checksum for DirectByteBuffer.
+// int java.util.zip.Adler32.updateByteBuffer(int crc, long buf, int off, int len)
+//
+bool LibraryCallKit::inline_updateByteBufferAdler32() {
+ assert(UseAdler32Intrinsics, "Adler32 Instrinsic support need"); // check if we actually need to check this flag or check a different one
+ assert(callee()->signature()->size() == 5, "updateByteBuffer has 4 parameters and one is long");
+ assert(callee()->holder()->is_loaded(), "Adler32 class must be loaded");
+ // no receiver since it is static method
+ Node* crc = argument(0); // type: int
+ Node* src = argument(1); // type: long
+ Node* offset = argument(3); // type: int
+ Node* length = argument(4); // type: int
+
+ src = ConvL2X(src); // adjust Java long to machine word
+ Node* base = _gvn.transform(new CastX2PNode(src));
+ offset = ConvI2X(offset);
+
+ // 'src_start' points to src array + scaled offset
+ Node* src_start = basic_plus_adr(top(), base, offset);
+
+ // Call the stub.
+ address stubAddr = StubRoutines::updateBytesAdler32();
+ const char *stubName = "updateBytesAdler32";
+
+ Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesAdler32_Type(),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ crc, src_start, length);
+
+ Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
+ set_result(result);
+ return true;
+}
+
//----------------------------inline_reference_get----------------------------
// public T java.lang.ref.Reference.get();
bool LibraryCallKit::inline_reference_get() {
--- a/hotspot/src/share/vm/opto/memnode.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/memnode.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1677,6 +1677,9 @@
if (klass == env->String_klass() &&
adr->is_AddP() && off != Type::OffsetBot) {
// For constant Strings treat the final fields as compile time constants.
+ // While we can list what field types java.lang.String has, it is more
+ // future-proof to handle all possible field types, anticipating future
+ // changes and experiments in String code.
Node* base = adr->in(AddPNode::Base);
const TypeOopPtr* t = phase->type(base)->isa_oopptr();
if (t != NULL && t->singleton()) {
@@ -1684,14 +1687,13 @@
if (field != NULL && field->is_final()) {
ciObject* string = t->const_oop();
ciConstant constant = string->as_instance()->field_value(field);
- if (constant.basic_type() == T_INT) {
- return TypeInt::make(constant.as_int());
- } else if (constant.basic_type() == T_ARRAY) {
- if (adr->bottom_type()->is_ptr_to_narrowoop()) {
- return TypeNarrowOop::make_from_constant(constant.as_object(), true);
- } else {
- return TypeOopPtr::make_from_constant(constant.as_object(), true);
- }
+ // Type::make_from_constant does not handle narrow oops, so handle it here.
+ // Everything else can use the factory method.
+ if ((constant.basic_type() == T_ARRAY || constant.basic_type() == T_OBJECT)
+ && adr->bottom_type()->is_ptr_to_narrowoop()) {
+ return TypeNarrowOop::make_from_constant(constant.as_object(), true);
+ } else {
+ return Type::make_from_constant(constant, true);
}
}
}
--- a/hotspot/src/share/vm/opto/runtime.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/runtime.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -33,7 +33,6 @@
#include "code/scopeDesc.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
#include "compiler/oopMap.hpp"
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/g1/heapRegion.hpp"
@@ -921,6 +920,28 @@
return TypeFunc::make(domain, range);
}
+/**
+* int updateBytesAdler32(int adler, bytes* b, int off, int len)
+*/
+const TypeFunc* OptoRuntime::updateBytesAdler32_Type() {
+ // create input type (domain)
+ int num_args = 3;
+ int argcnt = num_args;
+ const Type** fields = TypeTuple::fields(argcnt);
+ int argp = TypeFunc::Parms;
+ fields[argp++] = TypeInt::INT; // crc
+ fields[argp++] = TypePtr::NOTNULL; // src + offset
+ fields[argp++] = TypeInt::INT; // len
+ assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+ const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+ // result type needed
+ fields = TypeTuple::fields(1);
+ fields[TypeFunc::Parms+0] = TypeInt::INT; // crc result
+ const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
+ return TypeFunc::make(domain, range);
+}
+
// for cipherBlockChaining calls of aescrypt encrypt/decrypt, four pointers and a length, returning int
const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() {
// create input type (domain)
--- a/hotspot/src/share/vm/opto/runtime.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/runtime.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -331,6 +331,8 @@
static const TypeFunc* updateBytesCRC32_Type();
static const TypeFunc* updateBytesCRC32C_Type();
+ static const TypeFunc* updateBytesAdler32_Type();
+
// leaf on stack replacement interpreter accessor types
static const TypeFunc* osr_end_Type();
--- a/hotspot/src/share/vm/opto/stringopts.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/stringopts.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1576,51 +1576,58 @@
Node* result;
if (!kit.stopped()) {
+ Node* char_array = NULL;
+ if (sc->num_arguments() == 1 &&
+ (sc->mode(0) == StringConcat::StringMode ||
+ sc->mode(0) == StringConcat::StringNullCheckMode)) {
+ // Handle the case when there is only a single String argument.
+ // In this case, we can just pull the value from the String itself.
+ char_array = kit.load_String_value(kit.control(), sc->argument(0));
+ } else {
+ // length now contains the number of characters needed for the
+ // char[] so create a new AllocateArray for the char[]
+ {
+ PreserveReexecuteState preexecs(&kit);
+ // The original jvms is for an allocation of either a String or
+ // StringBuffer so no stack adjustment is necessary for proper
+ // reexecution. If we deoptimize in the slow path the bytecode
+ // will be reexecuted and the char[] allocation will be thrown away.
+ kit.jvms()->set_should_reexecute(true);
+ char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
+ length, 1);
+ }
- // length now contains the number of characters needed for the
- // char[] so create a new AllocateArray for the char[]
- Node* char_array = NULL;
- {
- PreserveReexecuteState preexecs(&kit);
- // The original jvms is for an allocation of either a String or
- // StringBuffer so no stack adjustment is necessary for proper
- // reexecution. If we deoptimize in the slow path the bytecode
- // will be reexecuted and the char[] allocation will be thrown away.
- kit.jvms()->set_should_reexecute(true);
- char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
- length, 1);
- }
-
- // Mark the allocation so that zeroing is skipped since the code
- // below will overwrite the entire array
- AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
- char_alloc->maybe_set_complete(_gvn);
+ // Mark the allocation so that zeroing is skipped since the code
+ // below will overwrite the entire array
+ AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
+ char_alloc->maybe_set_complete(_gvn);
- // Now copy the string representations into the final char[]
- Node* start = __ intcon(0);
- for (int argi = 0; argi < sc->num_arguments(); argi++) {
- Node* arg = sc->argument(argi);
- switch (sc->mode(argi)) {
- case StringConcat::IntMode: {
- Node* end = __ AddI(start, string_sizes->in(argi));
- // getChars words backwards so pass the ending point as well as the start
- int_getChars(kit, arg, char_array, start, end);
- start = end;
- break;
+ // Now copy the string representations into the final char[]
+ Node* start = __ intcon(0);
+ for (int argi = 0; argi < sc->num_arguments(); argi++) {
+ Node* arg = sc->argument(argi);
+ switch (sc->mode(argi)) {
+ case StringConcat::IntMode: {
+ Node* end = __ AddI(start, string_sizes->in(argi));
+ // getChars words backwards so pass the ending point as well as the start
+ int_getChars(kit, arg, char_array, start, end);
+ start = end;
+ break;
+ }
+ case StringConcat::StringNullCheckMode:
+ case StringConcat::StringMode: {
+ start = copy_string(kit, arg, char_array, start);
+ break;
+ }
+ case StringConcat::CharMode: {
+ __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
+ arg, T_CHAR, char_adr_idx, MemNode::unordered);
+ start = __ AddI(start, __ intcon(1));
+ break;
+ }
+ default:
+ ShouldNotReachHere();
}
- case StringConcat::StringNullCheckMode:
- case StringConcat::StringMode: {
- start = copy_string(kit, arg, char_array, start);
- break;
- }
- case StringConcat::CharMode: {
- __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
- arg, T_CHAR, char_adr_idx, MemNode::unordered);
- start = __ AddI(start, __ intcon(1));
- break;
- }
- default:
- ShouldNotReachHere();
}
}
--- a/hotspot/src/share/vm/opto/superword.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/superword.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1858,6 +1858,11 @@
vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n));
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
}
+ } else if (opc == Op_SqrtD) {
+ // Promote operand to vector (Sqrt is a 2 address instruction)
+ Node* in = vector_opd(p, 1);
+ vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n));
+ vlen_in_bytes = vn->as_Vector()->length_in_bytes();
} else {
ShouldNotReachHere();
}
--- a/hotspot/src/share/vm/opto/vectornode.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/vectornode.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -92,6 +92,9 @@
case Op_DivD:
assert(bt == T_DOUBLE, "must be");
return Op_DivVD;
+ case Op_SqrtD:
+ assert(bt == T_DOUBLE, "must be");
+ return Op_SqrtVD;
case Op_LShiftI:
switch (bt) {
case T_BOOLEAN:
@@ -277,6 +280,9 @@
case Op_DivVF: return new DivVFNode(n1, n2, vt);
case Op_DivVD: return new DivVDNode(n1, n2, vt);
+ // Currently only supports double precision sqrt
+ case Op_SqrtVD: return new SqrtVDNode(n1, vt);
+
case Op_LShiftVB: return new LShiftVBNode(n1, n2, vt);
case Op_LShiftVS: return new LShiftVSNode(n1, n2, vt);
case Op_LShiftVI: return new LShiftVINode(n1, n2, vt);
--- a/hotspot/src/share/vm/opto/vectornode.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/opto/vectornode.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -309,6 +309,14 @@
virtual int Opcode() const;
};
+//------------------------------SqrtVDNode--------------------------------------
+// Vector Sqrt double
+class SqrtVDNode : public VectorNode {
+ public:
+ SqrtVDNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {}
+ virtual int Opcode() const;
+};
+
//------------------------------LShiftVBNode-----------------------------------
// Vector left shift bytes
class LShiftVBNode : public VectorNode {
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -57,8 +57,6 @@
# include "classfile/classFileParser.hpp"
# include "classfile/classFileStream.hpp"
# include "classfile/classLoader.hpp"
-# include "classfile/imageDecompressor.hpp"
-# include "classfile/imageFile.hpp"
# include "classfile/javaClasses.hpp"
# include "classfile/symbolTable.hpp"
# include "classfile/systemDictionary.hpp"
@@ -232,7 +230,6 @@
# include "utilities/constantTag.hpp"
# include "utilities/copy.hpp"
# include "utilities/debug.hpp"
-# include "utilities/endian.hpp"
# include "utilities/exceptions.hpp"
# include "utilities/globalDefinitions.hpp"
# include "utilities/growableArray.hpp"
--- a/hotspot/src/share/vm/prims/jni.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/jni.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -3869,6 +3869,7 @@
void TestBufferingOopClosure_test();
void TestCodeCacheRemSet_test();
void FreeRegionList_test();
+void test_memset_with_concurrent_readers();
#endif
void execute_internal_vm_tests() {
@@ -3910,6 +3911,7 @@
if (UseG1GC) {
run_unit_test(FreeRegionList_test());
}
+ run_unit_test(test_memset_with_concurrent_readers());
#endif
tty->print_cr("All internal VM tests passed");
}
--- a/hotspot/src/share/vm/prims/jvm.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvm.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -24,8 +24,6 @@
#include "precompiled.hpp"
#include "classfile/classLoader.hpp"
-#include "classfile/imageDecompressor.hpp"
-#include "classfile/imageFile.hpp"
#include "classfile/javaAssertions.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/stringTable.hpp"
@@ -71,7 +69,6 @@
#include "utilities/copy.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/dtrace.hpp"
-#include "utilities/endian.hpp"
#include "utilities/events.hpp"
#include "utilities/histogram.hpp"
#include "utilities/macros.hpp"
@@ -3668,244 +3665,3 @@
info->is_attachable = AttachListener::is_attach_supported();
}
JVM_END
-
-// jdk.internal.jimage /////////////////////////////////////////////////////////
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-
-// Java entry to open an image file for sharing.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jlong,
-JVM_ImageOpen(JNIEnv *env, const char *nativePath, jboolean big_endian)) {
- JVMWrapper("JVM_ImageOpen");
- // Open image file for reading.
- ImageFileReader* reader = ImageFileReader::open(nativePath, big_endian != JNI_FALSE);
- // Return image ID as a jlong.
- return ImageFileReader::readerToID(reader);
-}
-JVM_END
-
-// Java entry for closing a shared image file.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(void,
-JVM_ImageClose(JNIEnv *env, jlong id)) {
- JVMWrapper("JVM_ImageClose");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // If valid reader the close.
- if (reader != NULL) {
- ImageFileReader::close(reader);
- }
-}
-JVM_END
-
-// Java entry for accessing the base address of the image index.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jlong,
-JVM_ImageGetIndexAddress(JNIEnv *env, jlong id)) {
- JVMWrapper("JVM_ImageGetIndexAddress");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // If valid reader return index base address (as jlong) else zero.
- return reader != NULL ? (jlong)reader->get_index_address() : 0L;
-}
-JVM_END
-
-// Java entry for accessing the base address of the image data.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jlong,
-JVM_ImageGetDataAddress(JNIEnv *env, jlong id)) {
- JVMWrapper("JVM_ImageGetDataAddress");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // If valid reader return data base address (as jlong) else zero.
- return MemoryMapImage && reader != NULL ? (jlong)reader->get_data_address() : 0L;
-}
-JVM_END
-
-// Java entry for reading an uncompressed resource from the image.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jboolean,
-JVM_ImageRead(JNIEnv *env, jlong id, jlong offset,
- unsigned char* uncompressedAddress, jlong uncompressed_size)) {
- JVMWrapper("JVM_ImageRead");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);\
- // If not a valid reader the fail the read.
- if (reader == NULL) return false;
- // Get the file offset of resource data.
- u8 file_offset = reader->get_index_size() + offset;
- // Check validity of arguments.
- if (offset < 0 ||
- uncompressed_size < 0 ||
- file_offset > reader->file_size() - uncompressed_size) {
- return false;
- }
- // Read file content into buffer.
- return (jboolean)reader->read_at((u1*)uncompressedAddress, uncompressed_size,
- file_offset);
-}
-JVM_END
-
-// Java entry for reading a compressed resource from the image.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jboolean,
-JVM_ImageReadCompressed(JNIEnv *env,
- jlong id, jlong offset,
- unsigned char* compressedAddress, jlong compressed_size,
- unsigned char* uncompressedAddress, jlong uncompressed_size)) {
- JVMWrapper("JVM_ImageReadCompressed");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // If not a valid reader the fail the read.
- if (reader == NULL) return false;
- // Get the file offset of resource data.
- u8 file_offset = reader->get_index_size() + offset;
- // Check validity of arguments.
- if (offset < 0 ||
- compressed_size < 0 ||
- uncompressed_size < 0 ||
- file_offset > reader->file_size() - compressed_size) {
- return false;
- }
-
- // Read file content into buffer.
- bool is_read = reader->read_at(compressedAddress, compressed_size,
- file_offset);
- // If successfully read then decompress.
- if (is_read) {
- const ImageStrings strings = reader->get_strings();
- ImageDecompressor::decompress_resource(compressedAddress, uncompressedAddress,
- uncompressed_size, &strings, true);
- }
- return (jboolean)is_read;
-}
-JVM_END
-
-// Java entry for retrieving UTF-8 bytes from image string table.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(const char*, JVM_ImageGetStringBytes(JNIEnv *env, jlong id, jint offset)) {
- JVMWrapper("JVM_ImageGetStringBytes");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // Fail if not valid reader.
- if (reader == NULL) return NULL;
- // Manage image string table.
- ImageStrings strings = reader->get_strings();
- // Retrieve string adrress from table.
- const char* data = strings.get(offset);
- return data;
-}
-JVM_END
-
-// Utility function to copy location information into a jlong array.
-// WARNING: This function is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-static void image_expand_location(JNIEnv *env, jlong* rawAttributes, ImageLocation& location) {
- // Copy attributes from location.
- for (int kind = ImageLocation::ATTRIBUTE_END + 1;
- kind < ImageLocation::ATTRIBUTE_COUNT;
- kind++) {
- rawAttributes[kind] = location.get_attribute(kind);
- }
-}
-
-// Java entry for retrieving location attributes for attribute offset.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jlong*, JVM_ImageGetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset)) {
- JVMWrapper("JVM_ImageGetAttributes");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // Fail if not valid reader.
- if (reader == NULL) return NULL;
- // Retrieve first byte address of resource's location attribute stream.
- u1* data = reader->get_location_offset_data(offset);
- // Fail if not valid offset.
- if (data == NULL) return NULL;
- // Expand stream into array.
- ImageLocation location(data);
- image_expand_location(env, rawAttributes, location);
- return rawAttributes;
-}
-JVM_END
-
-// Java entry for retrieving location attributes count for attribute offset.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jsize, JVM_ImageGetAttributesCount(JNIEnv *env)) {
- JVMWrapper("JVM_ImageGetAttributesCount");
- return ImageLocation::ATTRIBUTE_COUNT;
-}
-JVM_END
-
-// Java entry for retrieving location attributes for named resource.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jlong*,
-JVM_ImageFindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id)) {
- JVMWrapper("JVM_ImageFindAttributes");
- // Mark for temporary buffers.
- ResourceMark rm;
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // Fail if not valid reader.
- if (reader == NULL) return NULL;
- // Convert byte array to a cstring.
- char* path = NEW_RESOURCE_ARRAY(char, size + 1);
- memcpy(path, rawBytes, size);
- path[size] = '\0';
- // Locate resource location data.
- ImageLocation location;
- bool found = reader->find_location(path, location);
- // Resource not found.
- if (!found) return NULL;
- // Expand stream into array.
- image_expand_location(env, rawAttributes, location);
- return rawAttributes;
-}
-JVM_END
-
-// Java entry for retrieving all the attribute stream offsets from an image.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(jint*, JVM_ImageAttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id)) {
- JVMWrapper("JVM_ImageAttributeOffsets");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // Fail if not valid reader.
- if (reader == NULL) return NULL;
- // Determine endian for reader.
- Endian* endian = reader->endian();
- // Get base address of attribute stream offsets table.
- u4* offsets_table = reader->offsets_table();
- // Allocate int array result.
- // Copy values to result (converting endian.)
- for (u4 i = 0; i < length; i++) {
- rawOffsets[i] = endian->get(offsets_table[i]);
- }
- return rawOffsets;
-}
-JVM_END
-
-// Java entry for retrieving all the attribute stream offsets length from an image.
-// WARNING: This API is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-JVM_ENTRY(unsigned int, JVM_ImageAttributeOffsetsLength(JNIEnv *env, jlong id)) {
- JVMWrapper("JVM_ImageAttributeOffsetsLength");
- // Convert image ID to image reader structure.
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- // Fail if not valid reader.
- if (reader == NULL) return 0;
- // Get perfect hash table length.
- u4 length = reader->table_length();
- return (jint) length;
-}
-JVM_END
--- a/hotspot/src/share/vm/prims/jvm.h Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvm.h Mon Sep 14 07:03:04 2015 +0000
@@ -571,52 +571,6 @@
JNIEXPORT jboolean JNICALL
JVM_SupportsCX8(void);
-/*
- * jdk.internal.jimage
- * WARNING: This API is experimental and temporary during JDK 9 development
- * cycle. It will not be supported in the eventual JDK 9 release.
- */
-
-JNIEXPORT jlong JNICALL
-JVM_ImageOpen(JNIEnv *env, const char *nativePath, jboolean big_endian);
-
-JNIEXPORT void JNICALL
-JVM_ImageClose(JNIEnv *env, jlong id);
-
-JNIEXPORT jlong JNICALL
-JVM_ImageGetIndexAddress(JNIEnv *env, jlong id);
-
-JNIEXPORT jlong JNICALL
-JVM_ImageGetDataAddress(JNIEnv *env,jlong id);
-
-JNIEXPORT jboolean JNICALL
-JVM_ImageRead(JNIEnv *env, jlong id, jlong offset,
- unsigned char* uncompressedAddress, jlong uncompressed_size);
-
-
-JNIEXPORT jboolean JNICALL
-JVM_ImageReadCompressed(JNIEnv *env, jlong id, jlong offset,
- unsigned char* compressedBuffer, jlong compressed_size,
- unsigned char* uncompressedBuffer, jlong uncompressed_size);
-
-JNIEXPORT const char* JNICALL
-JVM_ImageGetStringBytes(JNIEnv *env, jlong id, jint offset);
-
-JNIEXPORT jlong* JNICALL
-JVM_ImageGetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset);
-
-JNIEXPORT jsize JNICALL
-JVM_ImageGetAttributesCount(JNIEnv *env);
-
-JNIEXPORT jlong* JNICALL
-JVM_ImageFindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id);
-
-JNIEXPORT jint* JNICALL
-JVM_ImageAttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id);
-
-JNIEXPORT unsigned int JNICALL
-JVM_ImageAttributeOffsetsLength(JNIEnv *env, jlong id);
-
/*************************************************************************
PART 2: Support for the Verifier and Class File Format Checker
************************************************************************/
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -3482,7 +3482,7 @@
for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
if (strcmp(property, p->key()) == 0) {
- if (p->set_value((char *)value_ptr)) {
+ if (p->set_value(value_ptr)) {
err = JVMTI_ERROR_NONE;
}
}
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -2181,8 +2181,8 @@
JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(f);
}
-void JvmtiExport::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
- JvmtiTagMap::weak_oops_do(is_alive, f);
+size_t JvmtiExport::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
+ return JvmtiTagMap::weak_oops_do(is_alive, f);
}
void JvmtiExport::gc_epilogue() {
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -366,7 +366,7 @@
static void clear_detected_exception (JavaThread* thread) NOT_JVMTI_RETURN;
static void oops_do(OopClosure* f) NOT_JVMTI_RETURN;
- static void weak_oops_do(BoolObjectClosure* b, OopClosure* f) NOT_JVMTI_RETURN;
+ static size_t weak_oops_do(BoolObjectClosure* b, OopClosure* f) NOT_JVMTI_RETURN_(0);
static void gc_epilogue() NOT_JVMTI_RETURN;
static void transition_pending_onload_raw_monitors() NOT_JVMTI_RETURN;
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -3284,32 +3284,35 @@
}
-void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
+size_t JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
// No locks during VM bring-up (0 threads) and no safepoints after main
// thread creation and before VMThread creation (1 thread); initial GC
// verification can happen in that window which gets to here.
assert(Threads::number_of_threads() <= 1 ||
SafepointSynchronize::is_at_safepoint(),
"must be executed at a safepoint");
+ size_t count = 0;
if (JvmtiEnv::environments_might_exist()) {
JvmtiEnvIterator it;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
JvmtiTagMap* tag_map = env->tag_map();
if (tag_map != NULL && !tag_map->is_empty()) {
- tag_map->do_weak_oops(is_alive, f);
+ count += tag_map->do_weak_oops(is_alive, f);
}
}
}
+ return count;
}
-void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
+size_t JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
// does this environment have the OBJECT_FREE event enabled
bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
// counters used for trace message
- int freed = 0;
- int moved = 0;
+ size_t freed = 0;
+ size_t moved = 0;
+ size_t stayed = 0;
JvmtiTagHashmap* hashmap = this->hashmap();
@@ -3318,7 +3321,7 @@
// if the hashmap is empty then we can skip it
if (hashmap->_entry_count == 0) {
- return;
+ return 0;
}
// now iterate through each entry in the table
@@ -3380,6 +3383,7 @@
} else {
// object didn't move
prev = entry;
+ stayed++;
}
}
@@ -3398,10 +3402,12 @@
// stats
if (TraceJVMTIObjectTagging) {
- int post_total = hashmap->_entry_count;
- int pre_total = post_total + freed;
-
- tty->print_cr("(%d->%d, %d freed, %d total moves)",
- pre_total, post_total, freed, moved);
+ size_t post_total = hashmap->_entry_count;
+ size_t pre_total = post_total + freed;
+
+ tty->print_cr("(" SIZE_FORMAT "->" SIZE_FORMAT ", " SIZE_FORMAT " freed, " SIZE_FORMAT " stayed, " SIZE_FORMAT " moved)",
+ pre_total, post_total, freed, stayed, moved);
}
+
+ return (freed + stayed + moved);
}
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -60,7 +60,7 @@
inline Mutex* lock() { return &_lock; }
inline JvmtiEnv* env() const { return _env; }
- void do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f);
+ size_t do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f);
// iterate over all entries in this tag map
void entry_iterate(JvmtiTagHashmapEntryClosure* closure);
@@ -122,8 +122,8 @@
jint* count_ptr, jobject** object_result_ptr,
jlong** tag_result_ptr);
- static void weak_oops_do(
- BoolObjectClosure* is_alive, OopClosure* f) NOT_JVMTI_RETURN;
+ static size_t weak_oops_do(BoolObjectClosure* is_alive,
+ OopClosure* f) NOT_JVMTI_RETURN_(0);
};
#endif // SHARE_VM_PRIMS_JVMTITAGMAP_HPP
--- a/hotspot/src/share/vm/prims/whitebox.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -27,7 +27,6 @@
#include <new>
#include "classfile/classLoaderData.hpp"
-#include "classfile/imageFile.hpp"
#include "classfile/stringTable.hpp"
#include "code/codeCache.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
@@ -56,6 +55,7 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "gc/parallel/parallelScavengeHeap.inline.hpp"
+#include "gc/parallel/adjoiningGenerations.hpp"
#endif // INCLUDE_ALL_GCS
#if INCLUDE_NMT
#include "services/mallocSiteTable.hpp"
@@ -297,6 +297,11 @@
return p->size() * HeapWordSize;
WB_END
+WB_ENTRY(jlong, WB_GetHeapSpaceAlignment(JNIEnv* env, jobject o))
+ size_t alignment = Universe::heap()->collector_policy()->space_alignment();
+ return (jlong)alignment;
+WB_END
+
#if INCLUDE_ALL_GCS
WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
G1CollectedHeap* g1 = G1CollectedHeap::heap();
@@ -335,6 +340,17 @@
return (jint)HeapRegion::GrainBytes;
WB_END
+WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o))
+ ParallelScavengeHeap* ps = ParallelScavengeHeap::heap();
+ size_t alignment = ps->gens()->virtual_spaces()->alignment();
+ return (jlong)alignment;
+WB_END
+
+WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o))
+ size_t alignment = ParallelScavengeHeap::heap()->generation_alignment();
+ return (jlong)alignment;
+WB_END
+
WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
ResourceMark rm(THREAD);
G1CollectedHeap* g1h = G1CollectedHeap::heap();
@@ -1025,11 +1041,18 @@
}
WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
- return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
+ if (size < 0) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
+ }
+ return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
WB_END
WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
- BufferBlob::free((BufferBlob*) addr);
+ if (addr == 0) {
+ return;
+ }
+ BufferBlob::free((BufferBlob*) addr);
WB_END
WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
@@ -1074,9 +1097,13 @@
WB_END
WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
- ThreadToNativeFromVM ttn(thread);
- CodeBlobStub stub((CodeBlob*) addr);
- return codeBlob2objectArray(thread, env, &stub);
+ if (addr == 0) {
+ THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
+ "WB_GetCodeBlob: addr is null");
+ }
+ ThreadToNativeFromVM ttn(thread);
+ CodeBlobStub stub((CodeBlob*) addr);
+ return codeBlob2objectArray(thread, env, &stub);
WB_END
WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
@@ -1144,131 +1171,7 @@
return (jlong) MetaspaceGC::capacity_until_GC();
WB_END
-WB_ENTRY(jboolean, WB_ReadImageFile(JNIEnv* env, jobject wb, jstring imagefile))
- const char* filename = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(imagefile));
- return ImageFileReader::open(filename) != NULL;
-WB_END
-WB_ENTRY(jlong, WB_imageOpenImage(JNIEnv *env, jobject wb, jstring path, jboolean big_endian))
- ThreadToNativeFromVM ttn(thread);
- const char *nativePath = env->GetStringUTFChars(path, NULL);
- jlong ret = JVM_ImageOpen(env, nativePath, big_endian);
-
- env->ReleaseStringUTFChars(path, nativePath);
- return ret;
-WB_END
-
-WB_ENTRY(void, WB_imageCloseImage(JNIEnv *env, jobject wb, jlong id))
- ThreadToNativeFromVM ttn(thread);
- JVM_ImageClose(env, id);
-WB_END
-
-WB_ENTRY(jlong, WB_imageGetIndexAddress(JNIEnv *env, jobject wb, jlong id))
- ThreadToNativeFromVM ttn(thread);
- return JVM_ImageGetIndexAddress(env, id);
-WB_END
-
-WB_ENTRY(jlong, WB_imageGetDataAddress(JNIEnv *env, jobject wb, jlong id))
- ThreadToNativeFromVM ttn(thread);
- return JVM_ImageGetDataAddress(env, id);
-WB_END
-
-WB_ENTRY(jboolean, WB_imageRead(JNIEnv *env, jobject wb, jlong id, jlong offset, jobject uncompressedBuffer, jlong uncompressed_size))
- ThreadToNativeFromVM ttn(thread);
- if (uncompressedBuffer == NULL) {
- return JNI_FALSE;
- }
- unsigned char* uncompressedAddress =
- (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
- return JVM_ImageRead(env, id, offset, uncompressedAddress, uncompressed_size);
-WB_END
-
-WB_ENTRY(jboolean, WB_imageReadCompressed(JNIEnv *env, jobject wb, jlong id, jlong offset, jobject compressedBuffer, jlong compressed_size, jobject uncompressedBuffer, jlong uncompressed_size))
- ThreadToNativeFromVM ttn(thread);
- if (uncompressedBuffer == NULL || compressedBuffer == NULL) {
- return false;
- }
- // Get address of read direct buffer.
- unsigned char* compressedAddress =
- (unsigned char*) env->GetDirectBufferAddress(compressedBuffer);
- // Get address of decompression direct buffer.
- unsigned char* uncompressedAddress =
- (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
- return JVM_ImageReadCompressed(env, id, offset, compressedAddress, compressed_size, uncompressedAddress, uncompressed_size);
-WB_END
-
-WB_ENTRY(jbyteArray, WB_imageGetStringBytes(JNIEnv *env, jobject wb, jlong id, jlong offset))
- ThreadToNativeFromVM ttn(thread);
- const char* data = JVM_ImageGetStringBytes(env, id, offset);
- // Determine String length.
- size_t size = strlen(data);
- // Allocate byte array.
- jbyteArray byteArray = env->NewByteArray((jsize) size);
- // Get array base address.
- jbyte* rawBytes = env->GetByteArrayElements(byteArray, NULL);
- // Copy bytes from image string table.
- memcpy(rawBytes, data, size);
- // Release byte array base address.
- env->ReleaseByteArrayElements(byteArray, rawBytes, 0);
- return byteArray;
-WB_END
-
-WB_ENTRY(jlong, WB_imageGetStringsSize(JNIEnv *env, jobject wb, jlong id))
- ImageFileReader* reader = ImageFileReader::idToReader(id);
- return reader? reader->strings_size() : 0L;
-WB_END
-
-WB_ENTRY(jlongArray, WB_imageGetAttributes(JNIEnv *env, jobject wb, jlong id, jint offset))
- ThreadToNativeFromVM ttn(thread);
- // Allocate a jlong large enough for all location attributes.
- jlongArray attributes = env->NewLongArray(JVM_ImageGetAttributesCount(env));
- // Get base address for jlong array.
- jlong* rawAttributes = env->GetLongArrayElements(attributes, NULL);
- jlong* ret = JVM_ImageGetAttributes(env, rawAttributes, id, offset);
- // Release jlong array base address.
- env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
- return ret == NULL ? NULL : attributes;
-WB_END
-
-WB_ENTRY(jlongArray, WB_imageFindAttributes(JNIEnv *env, jobject wb, jlong id, jbyteArray utf8))
- ThreadToNativeFromVM ttn(thread);
- // Allocate a jlong large enough for all location attributes.
- jlongArray attributes = env->NewLongArray(JVM_ImageGetAttributesCount(env));
- // Get base address for jlong array.
- jlong* rawAttributes = env->GetLongArrayElements(attributes, NULL);
- jsize size = env->GetArrayLength(utf8);
- jbyte* rawBytes = env->GetByteArrayElements(utf8, NULL);
- jlong* ret = JVM_ImageFindAttributes(env, rawAttributes, rawBytes, size, id);
- env->ReleaseByteArrayElements(utf8, rawBytes, 0);
- env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
- return ret == NULL ? NULL : attributes;
-WB_END
-
-WB_ENTRY(jintArray, WB_imageAttributeOffsets(JNIEnv *env, jobject wb, jlong id))
- ThreadToNativeFromVM ttn(thread);
- unsigned int length = JVM_ImageAttributeOffsetsLength(env, id);
- if (length == 0) {
- return NULL;
- }
- jintArray offsets = env->NewIntArray(length);
- // Get base address of result.
- jint* rawOffsets = env->GetIntArrayElements(offsets, NULL);
- jint* ret = JVM_ImageAttributeOffsets(env, rawOffsets, length, id);
- // Release result base address.
- env->ReleaseIntArrayElements(offsets, rawOffsets, 0);
- return ret == NULL ? NULL : offsets;
-WB_END
-
-WB_ENTRY(jint, WB_imageGetIntAtAddress(JNIEnv *env, jobject wb, jlong address, jint offset, jboolean big_endian))
- unsigned char* arr = (unsigned char*) address + offset;
- jint uraw;
- if (big_endian) {
- uraw = arr[0] << 24 | arr[1]<<16 | (arr[2]<<8) | arr[3];
- } else {
- uraw = arr[0] | arr[1]<<8 | (arr[2]<<16) | arr[3]<<24;
- }
- return uraw;
-WB_END
WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
@@ -1457,6 +1360,7 @@
{CC"getVMPageSize", CC"()I", (void*)&WB_GetVMPageSize },
{CC"getVMAllocationGranularity", CC"()J", (void*)&WB_GetVMAllocationGranularity },
{CC"getVMLargePageSize", CC"()J", (void*)&WB_GetVMLargePageSize},
+ {CC"getHeapSpaceAlignment", CC"()J", (void*)&WB_GetHeapSpaceAlignment},
{CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
{CC"parseCommandLine0",
CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
@@ -1481,6 +1385,8 @@
{CC"g1StartConcMarkCycle", CC"()Z", (void*)&WB_G1StartMarkCycle },
{CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
(void*)&WB_G1AuxiliaryMemoryUsage },
+ {CC"psVirtualSpaceAlignment",CC"()J", (void*)&WB_PSVirtualSpaceAlignment},
+ {CC"psHeapGenerationAlignment",CC"()J", (void*)&WB_PSHeapGenerationAlignment},
#endif // INCLUDE_ALL_GCS
#if INCLUDE_NMT
{CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc },
@@ -1576,21 +1482,6 @@
{CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
- {CC"readImageFile", CC"(Ljava/lang/String;)Z", (void*)&WB_ReadImageFile },
- {CC"imageOpenImage", CC"(Ljava/lang/String;Z)J",(void*)&WB_imageOpenImage },
- {CC"imageCloseImage", CC"(J)V", (void*)&WB_imageCloseImage },
- {CC"imageGetIndexAddress",CC"(J)J", (void*)&WB_imageGetIndexAddress},
- {CC"imageGetDataAddress",CC"(J)J", (void*)&WB_imageGetDataAddress},
- {CC"imageRead", CC"(JJLjava/nio/ByteBuffer;J)Z",
- (void*)&WB_imageRead },
- {CC"imageReadCompressed",CC"(JJLjava/nio/ByteBuffer;JLjava/nio/ByteBuffer;J)Z",
- (void*)&WB_imageReadCompressed},
- {CC"imageGetStringBytes",CC"(JI)[B", (void*)&WB_imageGetStringBytes},
- {CC"imageGetStringsSize",CC"(J)J", (void*)&WB_imageGetStringsSize},
- {CC"imageGetAttributes", CC"(JI)[J", (void*)&WB_imageGetAttributes},
- {CC"imageFindAttributes",CC"(J[B)[J", (void*)&WB_imageFindAttributes},
- {CC"imageAttributeOffsets",CC"(J)[I", (void*)&WB_imageAttributeOffsets},
- {CC"imageGetIntAtAddress",CC"(JIZ)I", (void*)&WB_imageGetIntAtAddress},
{CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
--- a/hotspot/src/share/vm/runtime/arguments.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -28,7 +28,6 @@
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "code/codeCacheExtensions.hpp"
-#include "compiler/compilerOracle.hpp"
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/referenceProcessor.hpp"
@@ -983,53 +982,61 @@
bool Arguments::add_property(const char* prop) {
const char* eq = strchr(prop, '=');
- char* key;
- // ns must be static--its address may be stored in a SystemProperty object.
- const static char ns[1] = {0};
- char* value = (char *)ns;
-
- size_t key_len = (eq == NULL) ? strlen(prop) : (eq - prop);
- key = AllocateHeap(key_len + 1, mtInternal);
- strncpy(key, prop, key_len);
- key[key_len] = '\0';
-
- if (eq != NULL) {
- size_t value_len = strlen(prop) - key_len - 1;
- value = AllocateHeap(value_len + 1, mtInternal);
- strncpy(value, &prop[key_len + 1], value_len + 1);
+ const char* key;
+ const char* value = "";
+
+ if (eq == NULL) {
+ // property doesn't have a value, thus use passed string
+ key = prop;
+ } else {
+ // property have a value, thus extract it and save to the
+ // allocated string
+ size_t key_len = eq - prop;
+ char* tmp_key = AllocateHeap(key_len + 1, mtInternal);
+
+ strncpy(tmp_key, prop, key_len);
+ tmp_key[key_len] = '\0';
+ key = tmp_key;
+
+ value = &prop[key_len + 1];
}
if (strcmp(key, "java.compiler") == 0) {
process_java_compiler_argument(value);
- FreeHeap(key);
- if (eq != NULL) {
- FreeHeap(value);
- }
- return true;
- } else if (strcmp(key, "sun.java.command") == 0) {
- _java_command = value;
-
// Record value in Arguments, but let it get passed to Java.
} else if (strcmp(key, "sun.java.launcher.is_altjvm") == 0 ||
strcmp(key, "sun.java.launcher.pid") == 0) {
// sun.java.launcher.is_altjvm and sun.java.launcher.pid property are
// private and are processed in process_sun_java_launcher_properties();
// the sun.java.launcher property is passed on to the java application
- FreeHeap(key);
- if (eq != NULL) {
- FreeHeap(value);
- }
- return true;
- } else if (strcmp(key, "java.vendor.url.bug") == 0) {
- // save it in _java_vendor_url_bug, so JVM fatal error handler can access
- // its value without going through the property list or making a Java call.
- _java_vendor_url_bug = value;
} else if (strcmp(key, "sun.boot.library.path") == 0) {
PropertyList_unique_add(&_system_properties, key, value, true);
- return true;
- }
- // Create new property and add at the end of the list
- PropertyList_unique_add(&_system_properties, key, value);
+ } else {
+ if (strcmp(key, "sun.java.command") == 0) {
+ if (_java_command != NULL) {
+ os::free(_java_command);
+ }
+ _java_command = os::strdup_check_oom(value, mtInternal);
+ } else if (strcmp(key, "java.vendor.url.bug") == 0) {
+ if (_java_vendor_url_bug != DEFAULT_VENDOR_URL_BUG) {
+ assert(_java_vendor_url_bug != NULL, "_java_vendor_url_bug is NULL");
+ os::free((void *)_java_vendor_url_bug);
+ }
+ // save it in _java_vendor_url_bug, so JVM fatal error handler can access
+ // its value without going through the property list or making a Java call.
+ _java_vendor_url_bug = os::strdup_check_oom(value, mtInternal);
+ }
+
+ // Create new property and add at the end of the list
+ PropertyList_unique_add(&_system_properties, key, value);
+ }
+
+ if (key != prop) {
+ // SystemProperty copy passed value, thus free previously allocated
+ // memory
+ FreeHeap((void *)key);
+ }
+
return true;
}
@@ -1046,7 +1053,7 @@
// Ensure Agent_OnLoad has the correct initial values.
// This may not be the final mode; mode may change later in onload phase.
PropertyList_unique_add(&_system_properties, "java.vm.info",
- (char*)VM_Version::vm_info_string(), false);
+ VM_Version::vm_info_string(), false);
UseInterpreter = true;
UseCompiler = true;
@@ -1583,9 +1590,6 @@
#endif // _LP64
#endif // !ZERO
- // Set up runtime image flags.
- set_runtime_image_flags();
-
CodeCacheExtensions::set_ergonomics_flags();
}
@@ -1840,16 +1844,6 @@
}
}
- // Set up runtime image flags
-void Arguments::set_runtime_image_flags() {
-#ifdef _LP64
- // Memory map image file by default on 64 bit machines.
- if (FLAG_IS_DEFAULT(MemoryMapImage)) {
- FLAG_SET_ERGO(bool, MemoryMapImage, true);
- }
-#endif
-}
-
// This must be called after ergonomics.
void Arguments::set_bytecode_flags() {
if (!RewriteBytecodes) {
@@ -1858,7 +1852,7 @@
}
// Aggressive optimization flags -XX:+AggressiveOpts
-void Arguments::set_aggressive_opts_flags() {
+jint Arguments::set_aggressive_opts_flags() {
#ifdef COMPILER2
if (AggressiveUnboxing) {
if (FLAG_IS_DEFAULT(EliminateAutoBox)) {
@@ -1885,7 +1879,9 @@
// Feed the cache size setting into the JDK
char buffer[1024];
sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax);
- add_property(buffer);
+ if (!add_property(buffer)) {
+ return JNI_ENOMEM;
+ }
}
if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) {
FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500);
@@ -1898,12 +1894,14 @@
// FLAG_SET_DEFAULT(EliminateZeroing, true);
// }
}
+
+ return JNI_OK;
}
//===========================================================================================================
// Parsing of java.compiler property
-void Arguments::process_java_compiler_argument(char* arg) {
+void Arguments::process_java_compiler_argument(const char* arg) {
// For backwards compatibility, Djava.compiler=NONE or ""
// causes us to switch to -Xint mode UNLESS -Xdebug
// is also specified.
@@ -3130,8 +3128,10 @@
jio_fprintf(defaultStream::output_stream(),
"CreateMinidumpOnCrash is replaced by CreateCoredumpOnCrash: CreateCoredumpOnCrash is off\n");
} else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx
- // Skip -XX:Flags= since that case has already been handled
- if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) {
+ // Skip -XX:Flags= and -XX:VMOptionsFile= since those cases have
+ // already been handled
+ if ((strncmp(tail, "Flags=", strlen("Flags=")) != 0) &&
+ (strncmp(tail, "VMOptionsFile=", strlen("VMOptionsFile=")) != 0)) {
if (!process_argument(tail, args->ignoreUnrecognized, origin)) {
return JNI_EINVAL;
}
@@ -3383,6 +3383,7 @@
class ScopedVMInitArgs : public StackObj {
private:
JavaVMInitArgs _args;
+ bool _is_set;
public:
ScopedVMInitArgs() {
@@ -3390,6 +3391,7 @@
_args.nOptions = 0;
_args.options = NULL;
_args.ignoreUnrecognized = false;
+ _is_set = false;
}
// Populates the JavaVMInitArgs object represented by this
@@ -3398,6 +3400,7 @@
// returns anything other than JNI_OK, then this object is in a
// partially constructed state, and should be abandoned.
jint set_args(GrowableArray<JavaVMOption>* options) {
+ _is_set = true;
JavaVMOption* options_arr = NEW_C_HEAP_ARRAY_RETURN_NULL(
JavaVMOption, options->length(), mtInternal);
if (options_arr == NULL) {
@@ -3421,6 +3424,7 @@
}
JavaVMInitArgs* get() { return &_args; }
+ bool is_set() { return _is_set; }
~ScopedVMInitArgs() {
if (_args.options == NULL) return;
@@ -3429,6 +3433,35 @@
}
FREE_C_HEAP_ARRAY(JavaVMOption, _args.options);
}
+
+ // Insert options into this option list, to replace option at
+ // vm_options_file_pos (-XX:VMOptionsFile)
+ jint insert(const JavaVMInitArgs* args,
+ const JavaVMInitArgs* args_to_insert,
+ const int vm_options_file_pos) {
+ assert(_args.options == NULL, "shouldn't be set yet");
+ assert(args_to_insert->nOptions != 0, "there should be args to insert");
+ assert(vm_options_file_pos != -1, "vm_options_file_pos should be set");
+
+ int length = args->nOptions + args_to_insert->nOptions - 1;
+ GrowableArray<JavaVMOption> *options = new (ResourceObj::C_HEAP, mtInternal)
+ GrowableArray<JavaVMOption>(length, true); // Construct new option array
+ for (int i = 0; i < args->nOptions; i++) {
+ if (i == vm_options_file_pos) {
+ // insert the new options starting at the same place as the
+ // -XX:VMOptionsFile option
+ for (int j = 0; j < args_to_insert->nOptions; j++) {
+ options->push(args_to_insert->options[j]);
+ }
+ } else {
+ options->push(args->options[i]);
+ }
+ }
+ // make into options array
+ jint result = set_args(options);
+ delete options;
+ return result;
+ }
};
jint Arguments::parse_java_options_environment_variable(ScopedVMInitArgs* args) {
@@ -3453,54 +3486,137 @@
return JNI_ENOMEM;
}
+ int retcode = parse_options_buffer(name, buffer, strlen(buffer), vm_args);
+
+ os::free(buffer);
+ return retcode;
+}
+
+const int OPTION_BUFFER_SIZE = 1024;
+
+jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* vm_args) {
+ // read file into buffer
+ int fd = ::open(file_name, O_RDONLY);
+ if (fd < 0) {
+ jio_fprintf(defaultStream::error_stream(),
+ "Could not open options file '%s'\n",
+ file_name);
+ return JNI_ERR;
+ }
+
+ // '+ 1' for NULL termination even with max bytes
+ int bytes_alloc = OPTION_BUFFER_SIZE + 1;
+
+ char *buf = NEW_C_HEAP_ARRAY_RETURN_NULL(char, bytes_alloc, mtInternal);
+ if (NULL == buf) {
+ jio_fprintf(defaultStream::error_stream(),
+ "Could not allocate read buffer for options file parse\n");
+ os::close(fd);
+ return JNI_ENOMEM;
+ }
+
+ memset(buf, 0, (unsigned)bytes_alloc);
+
+ // Fill buffer
+ // Use ::read() instead of os::read because os::read()
+ // might do a thread state transition
+ // and it is too early for that here
+
+ int bytes_read = ::read(fd, (void *)buf, (unsigned)bytes_alloc);
+ os::close(fd);
+ if (bytes_read < 0) {
+ FREE_C_HEAP_ARRAY(char, buf);
+ jio_fprintf(defaultStream::error_stream(),
+ "Could not read options file '%s'\n", file_name);
+ return JNI_ERR;
+ }
+
+ if (bytes_read == 0) {
+ // tell caller there is no option data and that is ok
+ FREE_C_HEAP_ARRAY(char, buf);
+ return JNI_OK;
+ }
+
+ // file is larger than OPTION_BUFFER_SIZE
+ if (bytes_read > bytes_alloc - 1) {
+ FREE_C_HEAP_ARRAY(char, buf);
+ jio_fprintf(defaultStream::error_stream(),
+ "Options file '%s' is larger than %d bytes.\n",
+ file_name, bytes_alloc - 1);
+ return JNI_EINVAL;
+ }
+
+ int retcode = parse_options_buffer(file_name, buf, bytes_read, vm_args);
+
+ FREE_C_HEAP_ARRAY(char, buf);
+ return retcode;
+}
+
+jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_t buf_len, ScopedVMInitArgs* vm_args) {
GrowableArray<JavaVMOption> *options = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JavaVMOption>(2, true); // Construct option array
- jio_fprintf(defaultStream::error_stream(),
- "Picked up %s: %s\n", name, buffer);
- char* rd = buffer; // pointer to the input string (rd)
- while (true) { // repeat for all options in the input string
- while (isspace(*rd)) rd++; // skip whitespace
- if (*rd == 0) break; // we re done when the input string is read completely
-
- // The output, option string, overwrites the input string.
- // Because of quoting, the pointer to the option string (wrt) may lag the pointer to
- // input string (rd).
- char* wrt = rd;
-
- JavaVMOption option;
- option.optionString = wrt;
- options->append(option); // Fill in option
- while (*rd != 0 && !isspace(*rd)) { // unquoted strings terminate with a space or NULL
+
+ // some pointers to help with parsing
+ char *buffer_end = buffer + buf_len;
+ char *opt_hd = buffer;
+ char *wrt = buffer;
+ char *rd = buffer;
+
+ // parse all options
+ while (rd < buffer_end) {
+ // skip leading white space from the input string
+ while (rd < buffer_end && isspace(*rd)) {
+ rd++;
+ }
+
+ if (rd >= buffer_end) {
+ break;
+ }
+
+ // Remember this is where we found the head of the token.
+ opt_hd = wrt;
+
+ // Tokens are strings of non white space characters separated
+ // by one or more white spaces.
+ while (rd < buffer_end && !isspace(*rd)) {
if (*rd == '\'' || *rd == '"') { // handle a quoted string
int quote = *rd; // matching quote to look for
rd++; // don't copy open quote
- while (*rd != quote) { // include everything (even spaces) up until quote
- if (*rd == 0) { // string termination means unmatched string
- jio_fprintf(defaultStream::error_stream(),
- "Unmatched quote in %s\n", name);
- delete options;
- os::free(buffer);
- return JNI_ERR;
- }
+ while (rd < buffer_end && *rd != quote) {
+ // include everything (even spaces)
+ // up until the close quote
*wrt++ = *rd++; // copy to option string
}
- rd++; // don't copy close quote
+
+ if (rd < buffer_end) {
+ rd++; // don't copy close quote
+ } else {
+ // did not see closing quote
+ jio_fprintf(defaultStream::error_stream(),
+ "Unmatched quote in %s\n", name);
+ delete options;
+ return JNI_ERR;
+ }
} else {
*wrt++ = *rd++; // copy to option string
}
}
- if (*rd != 0) {
- // In this case, the assignment to wrt below will make *rd nul,
- // which will interfere with the next loop iteration.
- rd++;
- }
- *wrt = 0; // Zero terminate option
+
+ // steal a white space character and set it to NULL
+ *wrt++ = '\0';
+ // We now have a complete token
+
+ JavaVMOption option;
+ option.optionString = opt_hd;
+
+ options->append(option); // Fill in option
+
+ rd++; // Advance to next character
}
// Fill out JavaVMInitArgs structure.
jint status = vm_args->set_args(options);
delete options;
- os::free(buffer);
return status;
}
@@ -3582,12 +3698,44 @@
return false;
}
+
#endif // PRODUCT
-static jint match_special_option_and_act(const JavaVMInitArgs* args,
- char** flags_file) {
+jint Arguments::insert_vm_options_file(const JavaVMInitArgs* args,
+ char** flags_file,
+ char** vm_options_file,
+ const int vm_options_file_pos,
+ ScopedVMInitArgs *vm_options_file_args,
+ ScopedVMInitArgs* args_out) {
+ jint code = parse_vm_options_file(*vm_options_file, vm_options_file_args);
+ if (code != JNI_OK) {
+ return code;
+ }
+
+ // Now set global settings from the vm_option file, giving an error if
+ // it has VMOptionsFile in it
+ code = match_special_option_and_act(vm_options_file_args->get(), flags_file,
+ NULL, NULL, NULL);
+ if (code != JNI_OK) {
+ return code;
+ }
+
+ if (vm_options_file_args->get()->nOptions < 1) {
+ return 0;
+ }
+
+ return args_out->insert(args, vm_options_file_args->get(),
+ vm_options_file_pos);
+}
+
+jint Arguments::match_special_option_and_act(const JavaVMInitArgs* args,
+ char ** flags_file,
+ char ** vm_options_file,
+ ScopedVMInitArgs* vm_options_file_args,
+ ScopedVMInitArgs* args_out) {
// Remaining part of option string
const char* tail;
+ int vm_options_file_pos = -1;
for (int index = 0; index < args->nOptions; index++) {
const JavaVMOption* option = args->options + index;
@@ -3596,6 +3744,35 @@
}
if (match_option(option, "-XX:Flags=", &tail)) {
*flags_file = (char *) tail;
+ if (*flags_file == NULL) {
+ jio_fprintf(defaultStream::error_stream(),
+ "Cannot copy flags_file name.\n");
+ return JNI_ENOMEM;
+ }
+ continue;
+ }
+ if (match_option(option, "-XX:VMOptionsFile=", &tail)) {
+ if (vm_options_file != NULL) {
+ // The caller accepts -XX:VMOptionsFile
+ if (*vm_options_file != NULL) {
+ jio_fprintf(defaultStream::error_stream(),
+ "Only one VM Options file is supported "
+ "on the command line\n");
+ return JNI_EINVAL;
+ }
+
+ *vm_options_file = (char *) tail;
+ vm_options_file_pos = index; // save position of -XX:VMOptionsFile
+ if (*vm_options_file == NULL) {
+ jio_fprintf(defaultStream::error_stream(),
+ "Cannot copy vm_options_file name.\n");
+ return JNI_ENOMEM;
+ }
+ } else {
+ jio_fprintf(defaultStream::error_stream(),
+ "VM options file is only supported on the command line\n");
+ return JNI_EINVAL;
+ }
continue;
}
if (match_option(option, "-XX:+PrintVMOptions")) {
@@ -3649,6 +3826,12 @@
}
#endif
}
+
+ // If there's a VMOptionsFile, parse that (also can set flags_file)
+ if ((vm_options_file != NULL) && (*vm_options_file != NULL)) {
+ return insert_vm_options_file(args, flags_file, vm_options_file,
+ vm_options_file_pos, vm_options_file_args, args_out);
+ }
return JNI_OK;
}
@@ -3673,10 +3856,15 @@
// If flag "-XX:Flags=flags-file" is used it will be the first option to be processed.
const char* hotspotrc = ".hotspotrc";
char* flags_file = NULL;
+ char* vm_options_file = NULL;
bool settings_file_specified = false;
bool needs_hotspotrc_warning = false;
ScopedVMInitArgs java_tool_options_args;
ScopedVMInitArgs java_options_args;
+ ScopedVMInitArgs modified_cmd_line_args;
+ // Pass in vm_options_file_args to keep memory for flags_file from being
+ // deallocated if found in the vm options file.
+ ScopedVMInitArgs vm_options_file_args;
jint code =
parse_java_tool_options_environment_variable(&java_tool_options_args);
@@ -3689,18 +3877,27 @@
return code;
}
- code =
- match_special_option_and_act(java_tool_options_args.get(), &flags_file);
+ code = match_special_option_and_act(java_tool_options_args.get(),
+ &flags_file, NULL, NULL, NULL);
+ if (code != JNI_OK) {
+ return code;
+ }
+
+ code = match_special_option_and_act(args, &flags_file, &vm_options_file,
+ &vm_options_file_args,
+ &modified_cmd_line_args);
if (code != JNI_OK) {
return code;
}
- code = match_special_option_and_act(args, &flags_file);
- if (code != JNI_OK) {
- return code;
- }
-
- code = match_special_option_and_act(java_options_args.get(), &flags_file);
+
+ // The command line arguments have been modified to include VMOptionsFile arguments.
+ if (modified_cmd_line_args.is_set()) {
+ args = modified_cmd_line_args.get();
+ }
+
+ code = match_special_option_and_act(java_options_args.get(), &flags_file,
+ NULL, NULL, NULL);
if (code != JNI_OK) {
return code;
}
@@ -3741,7 +3938,8 @@
// Parse JavaVMInitArgs structure passed in, as well as JAVA_TOOL_OPTIONS and _JAVA_OPTIONS
jint result = parse_vm_init_args(java_tool_options_args.get(),
- java_options_args.get(), args);
+ java_options_args.get(),
+ args); // command line arguments
if (result != JNI_OK) {
return result;
@@ -3870,7 +4068,10 @@
set_bytecode_flags();
// Set flags if Aggressive optimization flags (-XX:+AggressiveOpts) enabled
- set_aggressive_opts_flags();
+ jint code = set_aggressive_opts_flags();
+ if (code != JNI_OK) {
+ return code;
+ }
// Turn off biased locking for locking debug mode flags,
// which are subtly different from each other but neither works with
@@ -4036,7 +4237,7 @@
}
}
-void Arguments::PropertyList_add(SystemProperty** plist, const char* k, char* v) {
+void Arguments::PropertyList_add(SystemProperty** plist, const char* k, const char* v) {
if (plist == NULL)
return;
@@ -4049,7 +4250,7 @@
}
// This add maintains unique property key in the list.
-void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, char* v, jboolean append) {
+void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v, jboolean append) {
if (plist == NULL)
return;
--- a/hotspot/src/share/vm/runtime/arguments.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -60,7 +60,7 @@
char* value() const { return _value; }
SystemProperty* next() const { return _next; }
void set_next(SystemProperty* next) { _next = next; }
- bool set_value(char *value) {
+ bool set_value(const char *value) {
if (writeable()) {
if (_value != NULL) {
FreeHeap(_value);
@@ -346,8 +346,6 @@
static julong limit_by_allocatable_memory(julong size);
// Setup heap size
static void set_heap_size();
- // Set up runtime image flags
- static void set_runtime_image_flags();
// Based on automatic selection criteria, should the
// low pause collector be used.
static bool should_auto_select_low_pause_collector();
@@ -364,17 +362,31 @@
static bool add_property(const char* prop);
// Aggressive optimization flags.
- static void set_aggressive_opts_flags();
+ static jint set_aggressive_opts_flags();
// Argument parsing
static void do_pd_flag_adjustments();
static bool parse_argument(const char* arg, Flag::Flags origin);
static bool process_argument(const char* arg, jboolean ignore_unrecognized, Flag::Flags origin);
static void process_java_launcher_argument(const char*, void*);
- static void process_java_compiler_argument(char* arg);
+ static void process_java_compiler_argument(const char* arg);
static jint parse_options_environment_variable(const char* name, ScopedVMInitArgs* vm_args);
static jint parse_java_tool_options_environment_variable(ScopedVMInitArgs* vm_args);
static jint parse_java_options_environment_variable(ScopedVMInitArgs* vm_args);
+ static jint parse_vm_options_file(const char* file_name, ScopedVMInitArgs* vm_args);
+ static jint parse_options_buffer(const char* name, char* buffer, const size_t buf_len, ScopedVMInitArgs* vm_args);
+ static jint insert_vm_options_file(const JavaVMInitArgs* args,
+ char** flags_file,
+ char** vm_options_file,
+ const int vm_options_file_pos,
+ ScopedVMInitArgs* vm_options_file_args,
+ ScopedVMInitArgs* args_out);
+ static jint match_special_option_and_act(const JavaVMInitArgs* args,
+ char** flags_file,
+ char** vm_options_file,
+ ScopedVMInitArgs* vm_options_file_args,
+ ScopedVMInitArgs* args_out);
+
static jint parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
const JavaVMInitArgs *java_options_args,
const JavaVMInitArgs *cmd_line_args);
@@ -561,22 +573,22 @@
// Property List manipulation
static void PropertyList_add(SystemProperty *element);
static void PropertyList_add(SystemProperty** plist, SystemProperty *element);
- static void PropertyList_add(SystemProperty** plist, const char* k, char* v);
- static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v) {
+ static void PropertyList_add(SystemProperty** plist, const char* k, const char* v);
+ static void PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v) {
PropertyList_unique_add(plist, k, v, false);
}
- static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v, jboolean append);
+ static void PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v, jboolean append);
static const char* PropertyList_get_value(SystemProperty* plist, const char* key);
static int PropertyList_count(SystemProperty* pl);
static const char* PropertyList_get_key_at(SystemProperty* pl,int index);
static char* PropertyList_get_value_at(SystemProperty* pl,int index);
// Miscellaneous System property value getter and setters.
- static void set_dll_dir(char *value) { _sun_boot_library_path->set_value(value); }
- static void set_java_home(char *value) { _java_home->set_value(value); }
- static void set_library_path(char *value) { _java_library_path->set_value(value); }
+ static void set_dll_dir(const char *value) { _sun_boot_library_path->set_value(value); }
+ static void set_java_home(const char *value) { _java_home->set_value(value); }
+ static void set_library_path(const char *value) { _java_library_path->set_value(value); }
static void set_ext_dirs(char *value) { _ext_dirs = os::strdup_check_oom(value); }
- static void set_sysclasspath(char *value) { _sun_boot_class_path->set_value(value); }
+ static void set_sysclasspath(const char *value) { _sun_boot_class_path->set_value(value); }
static void append_sysclasspath(const char *value) { _sun_boot_class_path->append_value(value); }
static char* get_java_home() { return _java_home->value(); }
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -60,8 +60,8 @@
if ((UseConcMarkSweepGC || UseG1GC) && (value > PLAB::max_size())) {
CommandLineError::print(verbose,
"%s (" SIZE_FORMAT ") must be "
- "less than ergonomic PLAB maximum size (" SIZE_FORMAT ")\n",
- name, value, PLAB::min_size());
+ "less than or equal to ergonomic PLAB maximum size (" SIZE_FORMAT ")\n",
+ name, value, PLAB::max_size());
return Flag::VIOLATES_CONSTRAINT;
}
#endif // INCLUDE_ALL_GCS
--- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -26,7 +26,6 @@
#include "code/compiledIC.hpp"
#include "code/nmethod.hpp"
#include "code/scopeDesc.hpp"
-#include "compiler/compilerOracle.hpp"
#include "interpreter/interpreter.hpp"
#include "oops/methodData.hpp"
#include "oops/method.hpp"
--- a/hotspot/src/share/vm/runtime/globals.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -638,10 +638,6 @@
experimental(bool, AlwaysSafeConstructors, false, \
"Force safe construction, as if all fields are final.") \
\
- /* Temporary: See 6948537 */ \
- experimental(bool, UseMemSetInBOT, true, \
- "(Unstable) uses memset in BOT updates in GC code") \
- \
diagnostic(bool, UnlockDiagnosticVMOptions, trueInDebug, \
"Enable normal processing of flags relating to field diagnostics")\
\
@@ -820,7 +816,7 @@
\
product(bool, UseSHA1Intrinsics, false, \
"Use intrinsics for SHA-1 crypto hash function. " \
- "Requires that UseSHA is enabled.") \
+ "Requires that UseSHA is enabled.") \
\
product(bool, UseSHA256Intrinsics, false, \
"Use intrinsics for SHA-224 and SHA-256 crypto hash functions. " \
@@ -836,6 +832,9 @@
product(bool, UseCRC32CIntrinsics, false, \
"use intrinsics for java.util.zip.CRC32C") \
\
+ product(bool, UseAdler32Intrinsics, false, \
+ "use intrinsics for java.util.zip.Adler32") \
+ \
diagnostic(ccstrlist, DisableIntrinsic, "", \
"do not expand intrinsics whose (internal) names appear here") \
\
@@ -1091,9 +1090,6 @@
product(bool, AlwaysRestoreFPU, false, \
"Restore the FPU control word after every JNI call (expensive)") \
\
- product(bool, MemoryMapImage, false, \
- "Memory map entire runtime image") \
- \
diagnostic(bool, PrintCompilation2, false, \
"Print additional statistics per compilation") \
\
@@ -1603,7 +1599,7 @@
"(ParallelGC only)") \
\
product(bool, ScavengeBeforeFullGC, true, \
- "Scavenge youngest generation before each full GC.") \
+ "Scavenge young generation before each full GC.") \
\
develop(bool, ScavengeWithObjectsInToSpace, false, \
"Allow scavenges to occur when to-space contains objects") \
@@ -2101,11 +2097,11 @@
"promotion failure") \
\
notproduct(bool, PromotionFailureALot, false, \
- "Use promotion failure handling on every youngest generation " \
+ "Use promotion failure handling on every young generation " \
"collection") \
\
develop(uintx, PromotionFailureALotCount, 1000, \
- "Number of promotion failures occurring at PLAB " \
+ "Number of promotion failures occurring at PLAB " \
"refill attempts (ParNew) or promotion attempts " \
"(other young collectors)") \
\
--- a/hotspot/src/share/vm/runtime/init.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/init.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -83,7 +83,6 @@
// during VM shutdown
void perfMemory_exit();
void ostream_exit();
-bool image_decompressor_init();
void vm_init_globals() {
check_ThreadShadow();
@@ -122,9 +121,6 @@
templateTable_init();
InterfaceSupport_init();
SharedRuntime::generate_stubs();
- if (!image_decompressor_init()) {
- return JNI_ERR;
- }
universe2_init(); // dependent on codeCache_init and stubRoutines_init1
referenceProcessor_init();
jni_handles_init();
--- a/hotspot/src/share/vm/runtime/jniHandles.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/jniHandles.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -124,8 +124,8 @@
}
-void JNIHandles::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
- _weak_global_handles->weak_oops_do(is_alive, f);
+size_t JNIHandles::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
+ return _weak_global_handles->weak_oops_do(is_alive, f);
}
@@ -380,8 +380,9 @@
}
-void JNIHandleBlock::weak_oops_do(BoolObjectClosure* is_alive,
- OopClosure* f) {
+size_t JNIHandleBlock::weak_oops_do(BoolObjectClosure* is_alive,
+ OopClosure* f) {
+ size_t count = 0;
for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
assert(current->pop_frame_link() == NULL,
"blocks holding weak global JNI handles should not have pop frame link set");
@@ -390,6 +391,7 @@
oop value = *root;
// traverse heap pointers only, not deleted handles or free list pointers
if (value != NULL && Universe::heap()->is_in_reserved(value)) {
+ count++;
if (is_alive->do_object_b(value)) {
// The weakly referenced object is alive, update pointer
f->do_oop(root);
@@ -412,7 +414,9 @@
* JVMTI data structures may also contain weak oops. The iteration of them
* is placed here so that we don't need to add it to each of the collectors.
*/
- JvmtiExport::weak_oops_do(is_alive, f);
+ count += JvmtiExport::weak_oops_do(is_alive, f);
+
+ return count;
}
--- a/hotspot/src/share/vm/runtime/jniHandles.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/jniHandles.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -85,7 +85,7 @@
// Traversal of regular global handles
static void oops_do(OopClosure* f);
// Traversal of weak global handles. Unreachable oops are cleared.
- static void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
+ static size_t weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
};
@@ -153,7 +153,7 @@
// Traversal of regular handles
void oops_do(OopClosure* f);
// Traversal of weak handles. Unreachable oops are cleared.
- void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
+ size_t weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
// Checked JNI support
void set_planned_capacity(size_t planned_capacity) { _planned_capacity = planned_capacity; }
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -100,7 +100,6 @@
Mutex* ExceptionCache_lock = NULL;
Monitor* ObjAllocPost_lock = NULL;
Mutex* OsrList_lock = NULL;
-Mutex* ImageFileReaderTable_lock = NULL;
#ifndef PRODUCT
Mutex* FullGCALot_lock = NULL;
@@ -228,7 +227,6 @@
def(ProfilePrint_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing
def(ExceptionCache_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing
def(OsrList_lock , Mutex , leaf, true, Monitor::_safepoint_check_never);
- def(ImageFileReaderTable_lock , Mutex , nonleaf, false, Monitor::_safepoint_check_always); // synchronize image readers open/close
def(Debug1_lock , Mutex , leaf, true, Monitor::_safepoint_check_never);
#ifndef PRODUCT
def(FullGCALot_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // a lock to make FullGCALot MT safe
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -102,7 +102,6 @@
extern Mutex* ProfilePrint_lock; // a lock used to serialize the printing of profiles
extern Mutex* ExceptionCache_lock; // a lock used to synchronize exception cache updates
extern Mutex* OsrList_lock; // a lock used to serialize access to OSR queues
-extern Mutex* ImageFileReaderTable_lock; // a lock used to synchronize image readers open/close
#ifndef PRODUCT
extern Mutex* FullGCALot_lock; // a lock to make FullGCALot MT safe
--- a/hotspot/src/share/vm/runtime/objectMonitor.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -184,7 +184,8 @@
//
// * The monitor entry list operations avoid locks, but strictly speaking
// they're not lock-free. Enter is lock-free, exit is not.
-// See http://j2se.east/~dice/PERSIST/040825-LockFreeQueues.html
+// For a description of 'Methods and apparatus providing non-blocking access
+// to a resource,' see U.S. Pat. No. 7844973.
//
// * The cxq can have multiple concurrent "pushers" but only one concurrent
// detaching thread. This mechanism is immune from the ABA corruption.
@@ -405,9 +406,7 @@
event.commit();
}
- if (ObjectMonitor::_sync_ContendedLockAttempts != NULL) {
- ObjectMonitor::_sync_ContendedLockAttempts->inc();
- }
+ OM_PERFDATA_OP(ContendedLockAttempts, inc());
}
@@ -574,9 +573,9 @@
// That is by design - we trade "lossy" counters which are exposed to
// races during updates for a lower probe effect.
TEVENT(Inflated enter - Futile wakeup);
- if (ObjectMonitor::_sync_FutileWakeups != NULL) {
- ObjectMonitor::_sync_FutileWakeups->inc();
- }
+ // This PerfData object can be used in parallel with a safepoint.
+ // See the work around in PerfDataManager::destroy().
+ OM_PERFDATA_OP(FutileWakeups, inc());
++nWakeups;
// Assuming this is not a spurious wakeup we'll normally find _succ == Self.
@@ -748,9 +747,9 @@
// *must* retry _owner before parking.
OrderAccess::fence();
- if (ObjectMonitor::_sync_FutileWakeups != NULL) {
- ObjectMonitor::_sync_FutileWakeups->inc();
- }
+ // This PerfData object can be used in parallel with a safepoint.
+ // See the work around in PerfDataManager::destroy().
+ OM_PERFDATA_OP(FutileWakeups, inc());
}
// Self has acquired the lock -- Unlink Self from the cxq or EntryList .
@@ -1302,9 +1301,7 @@
Trigger->unpark();
// Maintain stats and report events to JVMTI
- if (ObjectMonitor::_sync_Parks != NULL) {
- ObjectMonitor::_sync_Parks->inc();
- }
+ OM_PERFDATA_OP(Parks, inc());
}
@@ -1765,9 +1762,7 @@
}
DTRACE_MONITOR_PROBE(notify, this, object(), THREAD);
INotify(THREAD);
- if (ObjectMonitor::_sync_Notifications != NULL) {
- ObjectMonitor::_sync_Notifications->inc(1);
- }
+ OM_PERFDATA_OP(Notifications, inc(1));
}
@@ -1792,9 +1787,7 @@
INotify(THREAD);
}
- if (tally != 0 && ObjectMonitor::_sync_Notifications != NULL) {
- ObjectMonitor::_sync_Notifications->inc(tally);
- }
+ OM_PERFDATA_OP(Notifications, inc(tally));
}
// -----------------------------------------------------------------------------
@@ -1816,7 +1809,8 @@
// (duration) or we can fix the count at approximately the duration of
// a context switch and vary the frequency. Of course we could also
// vary both satisfying K == Frequency * Duration, where K is adaptive by monitor.
-// See http://j2se.east/~dice/PERSIST/040824-AdaptiveSpinning.html.
+// For a description of 'Adaptive spin-then-block mutual exclusion in
+// multi-threaded processing,' see U.S. Pat. No. 8046758.
//
// This implementation varies the duration "D", where D varies with
// the success rate of recent spin attempts. (D is capped at approximately
--- a/hotspot/src/share/vm/runtime/objectMonitor.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/objectMonitor.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -177,6 +177,19 @@
public:
static void Initialize();
+
+ // Only perform a PerfData operation if the PerfData object has been
+ // allocated and if the PerfDataManager has not freed the PerfData
+ // objects which can happen at normal VM shutdown.
+ //
+ #define OM_PERFDATA_OP(f, op_str) \
+ do { \
+ if (ObjectMonitor::_sync_ ## f != NULL && \
+ PerfDataManager::has_PerfData()) { \
+ ObjectMonitor::_sync_ ## f->op_str; \
+ } \
+ } while (0)
+
static PerfCounter * _sync_ContendedLockAttempts;
static PerfCounter * _sync_FutileWakeups;
static PerfCounter * _sync_Parks;
--- a/hotspot/src/share/vm/runtime/perfData.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/perfData.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -39,6 +39,7 @@
PerfDataList* PerfDataManager::_all = NULL;
PerfDataList* PerfDataManager::_sampled = NULL;
PerfDataList* PerfDataManager::_constants = NULL;
+volatile bool PerfDataManager::_has_PerfData = 0;
/*
* The jvmstat global and subsystem jvmstat counter name spaces. The top
@@ -272,16 +273,22 @@
}
-
-
-
-
void PerfDataManager::destroy() {
if (_all == NULL)
// destroy already called, or initialization never happened
return;
+ // Clear the flag before we free the PerfData counters. Thus begins
+ // the race between this thread and another thread that has just
+ // queried PerfDataManager::has_PerfData() and gotten back 'true'.
+ // The hope is that the other thread will finish its PerfData
+ // manipulation before we free the memory. The two alternatives are
+ // 1) leak the PerfData memory or 2) do some form of synchronized
+ // access or check before every PerfData operation.
+ _has_PerfData = false;
+ os::naked_short_sleep(1); // 1ms sleep to let other thread(s) run
+
for (int index = 0; index < _all->length(); index++) {
PerfData* p = _all->at(index);
delete p;
@@ -302,6 +309,7 @@
if (_all == NULL) {
_all = new PerfDataList(100);
+ _has_PerfData = true;
}
assert(!_all->contains(p->name()), "duplicate name added");
--- a/hotspot/src/share/vm/runtime/perfData.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/perfData.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -668,6 +668,7 @@
static PerfDataList* _sampled;
static PerfDataList* _constants;
static const char* _name_spaces[];
+ static volatile bool _has_PerfData;
// add a PerfData item to the list(s) of know PerfData objects
static void add_item(PerfData* p, bool sampled);
@@ -869,6 +870,7 @@
}
static void destroy();
+ static bool has_PerfData() { return _has_PerfData; }
};
// Useful macros to create the performance counters
--- a/hotspot/src/share/vm/runtime/perfMemory.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/perfMemory.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -32,6 +32,7 @@
#include "runtime/os.hpp"
#include "runtime/perfData.hpp"
#include "runtime/perfMemory.hpp"
+#include "runtime/safepoint.hpp"
#include "runtime/statSampler.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -64,16 +65,20 @@
if (!UsePerfData) return;
if (!PerfMemory::is_initialized()) return;
- // if the StatSampler is active, then we don't want to remove
- // resources it may be dependent on. Typically, the StatSampler
- // is disengaged from the watcher thread when this method is called,
- // but it is not disengaged if this method is invoked during a
- // VM abort.
+ // Only destroy PerfData objects if we're at a safepoint and the
+ // StatSampler is not active. Otherwise, we risk removing PerfData
+ // objects that are currently being used by running JavaThreads
+ // or the StatSampler. This method is invoked while we are not at
+ // a safepoint during a VM abort so leaving the PerfData objects
+ // around may also help diagnose the failure. In rare cases,
+ // PerfData objects are used in parallel with a safepoint. See
+ // the work around in PerfDataManager::destroy().
//
- if (!StatSampler::is_active())
+ if (SafepointSynchronize::is_at_safepoint() && !StatSampler::is_active()) {
PerfDataManager::destroy();
+ }
- // remove the persistent external resources, if any. this method
+ // Remove the persistent external resources, if any. This method
// does not unmap or invalidate any virtual memory allocated during
// initialization.
//
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -32,7 +32,6 @@
#include "code/vtableStubs.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/gcLocker.inline.hpp"
#include "interpreter/interpreter.hpp"
@@ -2622,7 +2621,7 @@
if (nm != NULL) {
if (PrintCompilation) {
ttyLocker ttyl;
- CompileTask::print_compilation(tty, nm, method->is_static() ? "(static)" : "");
+ CompileTask::print(tty, nm, method->is_static() ? "(static)" : "");
}
nm->post_compiled_method_load_event();
}
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -139,6 +139,7 @@
address StubRoutines::_crc_table_adr = NULL;
address StubRoutines::_updateBytesCRC32C = NULL;
+address StubRoutines::_updateBytesAdler32 = NULL;
address StubRoutines::_multiplyToLen = NULL;
address StubRoutines::_squareToLen = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -198,6 +198,7 @@
static address _crc_table_adr;
static address _updateBytesCRC32C;
+ static address _updateBytesAdler32;
static address _multiplyToLen;
static address _squareToLen;
@@ -364,6 +365,7 @@
static address crc_table_addr() { return _crc_table_adr; }
static address updateBytesCRC32C() { return _updateBytesCRC32C; }
+ static address updateBytesAdler32() { return _updateBytesAdler32; }
static address multiplyToLen() {return _multiplyToLen; }
static address squareToLen() {return _squareToLen; }
--- a/hotspot/src/share/vm/runtime/sweeper.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -611,7 +611,7 @@
} else if (nm->is_not_entrant()) {
// If there are no current activations of this method on the
// stack we can safely convert it to a zombie method
- if (nm->can_not_entrant_be_converted()) {
+ if (nm->can_convert_to_zombie()) {
// Clear ICStubs to prevent back patching stubs of zombie or unloaded
// nmethods during the next safepoint (see ICStub::finalize).
{
@@ -645,6 +645,12 @@
assert(result == None, "sanity");
result = Flushed;
} else {
+ {
+ // Clean ICs of unloaded nmethods as well because they may reference other
+ // unloaded nmethods that may be flushed earlier in the sweeper cycle.
+ MutexLocker cl(CompiledIC_lock);
+ nm->cleanup_inline_caches();
+ }
// Code cache state change is tracked in make_zombie()
nm->make_zombie();
SWEEP(nm);
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -189,9 +189,7 @@
mon->INotify(self);
++tally;
} while (mon->first_waiter() != NULL && all);
- if (ObjectMonitor::_sync_Notifications != NULL) {
- ObjectMonitor::_sync_Notifications->inc(tally);
- }
+ OM_PERFDATA_OP(Notifications, inc(tally));
}
return true;
}
@@ -1362,7 +1360,7 @@
}
// We've successfully installed INFLATING (0) into the mark-word.
- // This is the only case where 0 will appear in a mark-work.
+ // This is the only case where 0 will appear in a mark-word.
// Only the singular thread that successfully swings the mark-word
// to 0 can perform (or more precisely, complete) inflation.
//
@@ -1413,7 +1411,7 @@
// Hopefully the performance counters are allocated on distinct cache lines
// to avoid false sharing on MP systems ...
- if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc();
+ OM_PERFDATA_OP(Inflations, inc());
TEVENT(Inflate: overwrite stacklock);
if (TraceMonitorInflation) {
if (object->is_instance()) {
@@ -1461,7 +1459,7 @@
// Hopefully the performance counters are allocated on distinct
// cache lines to avoid false sharing on MP systems ...
- if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc();
+ OM_PERFDATA_OP(Inflations, inc());
TEVENT(Inflate: overwrite neutral);
if (TraceMonitorInflation) {
if (object->is_instance()) {
@@ -1678,8 +1676,8 @@
}
Thread::muxRelease(&gListLock);
- if (ObjectMonitor::_sync_Deflations != NULL) ObjectMonitor::_sync_Deflations->inc(nScavenged);
- if (ObjectMonitor::_sync_MonExtant != NULL) ObjectMonitor::_sync_MonExtant ->set_value(nInCirculation);
+ OM_PERFDATA_OP(Deflations, inc(nScavenged));
+ OM_PERFDATA_OP(MonExtant, set_value(nInCirculation));
// TODO: Add objectMonitor leak detection.
// Audit/inventory the objectMonitors -- make sure they're all accounted for.
--- a/hotspot/src/share/vm/runtime/thread.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/thread.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -368,9 +368,17 @@
inline void clear_critical_native_unlock();
// Support for Unhandled Oop detection
+ // Add the field for both, fastdebug and debug, builds to keep
+ // Thread's fields layout the same.
+ // Note: CHECK_UNHANDLED_OOPS is defined only for fastdebug build.
#ifdef CHECK_UNHANDLED_OOPS
private:
UnhandledOops* _unhandled_oops;
+#elif defined(ASSERT)
+ private:
+ void* _unhandled_oops;
+#endif
+#ifdef CHECK_UNHANDLED_OOPS
public:
UnhandledOops* unhandled_oops() { return _unhandled_oops; }
// Mark oop safe for gc. It may be stack allocated but won't move.
@@ -383,12 +391,12 @@
}
#endif // CHECK_UNHANDLED_OOPS
+ public:
#ifndef PRODUCT
bool skip_gcalot() { return _skip_gcalot; }
void set_skip_gcalot(bool v) { _skip_gcalot = v; }
#endif
- public:
// Installs a pending exception to be inserted later
static void send_async_exception(oop thread_oop, oop java_throwable);
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -283,17 +283,17 @@
volatile_nonstatic_field(ArrayKlass, _higher_dimension, Klass*) \
volatile_nonstatic_field(ArrayKlass, _lower_dimension, Klass*) \
nonstatic_field(ArrayKlass, _vtable_len, int) \
- nonstatic_field(CompiledICHolder, _holder_method, Method*) \
- nonstatic_field(CompiledICHolder, _holder_klass, Klass*) \
- nonstatic_field(ConstantPool, _tags, Array<u1>*) \
- nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \
- nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
- nonstatic_field(ConstantPool, _operands, Array<u2>*) \
- nonstatic_field(ConstantPool, _length, int) \
- nonstatic_field(ConstantPool, _resolved_references, jobject) \
- nonstatic_field(ConstantPool, _reference_map, Array<u2>*) \
- nonstatic_field(ConstantPoolCache, _length, int) \
- nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
+ nonstatic_field(CompiledICHolder, _holder_method, Method*) \
+ nonstatic_field(CompiledICHolder, _holder_klass, Klass*) \
+ nonstatic_field(ConstantPool, _tags, Array<u1>*) \
+ nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \
+ nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
+ nonstatic_field(ConstantPool, _operands, Array<u2>*) \
+ nonstatic_field(ConstantPool, _length, int) \
+ nonstatic_field(ConstantPool, _resolved_references, jobject) \
+ nonstatic_field(ConstantPool, _reference_map, Array<u2>*) \
+ nonstatic_field(ConstantPoolCache, _length, int) \
+ nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
nonstatic_field(InstanceKlass, _array_klasses, Klass*) \
nonstatic_field(InstanceKlass, _methods, Array<Method*>*) \
nonstatic_field(InstanceKlass, _default_methods, Array<Method*>*) \
@@ -303,12 +303,12 @@
nonstatic_field(InstanceKlass, _java_fields_count, u2) \
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
nonstatic_field(InstanceKlass, _class_loader_data, ClassLoaderData*) \
- nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
+ nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
nonstatic_field(InstanceKlass, _source_debug_extension, char*) \
- nonstatic_field(InstanceKlass, _inner_classes, Array<jushort>*) \
+ nonstatic_field(InstanceKlass, _inner_classes, Array<jushort>*) \
nonstatic_field(InstanceKlass, _nonstatic_field_size, int) \
nonstatic_field(InstanceKlass, _static_field_size, int) \
- nonstatic_field(InstanceKlass, _static_oop_field_count, u2) \
+ nonstatic_field(InstanceKlass, _static_oop_field_count, u2) \
nonstatic_field(InstanceKlass, _nonstatic_oop_map_size, int) \
nonstatic_field(InstanceKlass, _is_marked_dependent, bool) \
nonstatic_field(InstanceKlass, _minor_version, u2) \
@@ -346,62 +346,62 @@
nonstatic_field(Klass, _prototype_header, markOop) \
nonstatic_field(Klass, _next_sibling, Klass*) \
nonstatic_field(vtableEntry, _method, Method*) \
- nonstatic_field(MethodData, _size, int) \
- nonstatic_field(MethodData, _method, Method*) \
- nonstatic_field(MethodData, _data_size, int) \
- nonstatic_field(MethodData, _data[0], intptr_t) \
- nonstatic_field(MethodData, _parameters_type_data_di, int) \
- nonstatic_field(MethodData, _nof_decompiles, uint) \
- nonstatic_field(MethodData, _nof_overflow_recompiles, uint) \
- nonstatic_field(MethodData, _nof_overflow_traps, uint) \
- nonstatic_field(MethodData, _trap_hist._array[0], u1) \
- nonstatic_field(MethodData, _eflags, intx) \
- nonstatic_field(MethodData, _arg_local, intx) \
- nonstatic_field(MethodData, _arg_stack, intx) \
- nonstatic_field(MethodData, _arg_returned, intx) \
- nonstatic_field(MethodData, _tenure_traps, uint) \
- nonstatic_field(MethodData, _invoke_mask, int) \
- nonstatic_field(MethodData, _backedge_mask, int) \
- nonstatic_field(DataLayout, _header._struct._tag, u1) \
- nonstatic_field(DataLayout, _header._struct._flags, u1) \
- nonstatic_field(DataLayout, _header._struct._bci, u2) \
- nonstatic_field(DataLayout, _cells[0], intptr_t) \
- nonstatic_field(MethodCounters, _nmethod_age, int) \
- nonstatic_field(MethodCounters, _interpreter_invocation_limit, int) \
- nonstatic_field(MethodCounters, _interpreter_backward_branch_limit, int) \
- nonstatic_field(MethodCounters, _interpreter_profile_limit, int) \
- nonstatic_field(MethodCounters, _invoke_mask, int) \
- nonstatic_field(MethodCounters, _backedge_mask, int) \
- nonstatic_field(MethodCounters, _interpreter_invocation_count, int) \
- nonstatic_field(MethodCounters, _interpreter_throwout_count, u2) \
- nonstatic_field(MethodCounters, _number_of_breakpoints, u2) \
- nonstatic_field(MethodCounters, _invocation_counter, InvocationCounter) \
- nonstatic_field(MethodCounters, _backedge_counter, InvocationCounter) \
- nonstatic_field(Method, _constMethod, ConstMethod*) \
- nonstatic_field(Method, _method_data, MethodData*) \
- nonstatic_field(Method, _method_counters, MethodCounters*) \
- nonstatic_field(Method, _access_flags, AccessFlags) \
- nonstatic_field(Method, _vtable_index, int) \
- nonstatic_field(Method, _method_size, u2) \
- nonstatic_field(Method, _intrinsic_id, u1) \
- nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \
- volatile_nonstatic_field(Method, _code, nmethod*) \
- nonstatic_field(Method, _i2i_entry, address) \
- nonstatic_field(Method, _adapter, AdapterHandlerEntry*) \
- volatile_nonstatic_field(Method, _from_compiled_entry, address) \
- volatile_nonstatic_field(Method, _from_interpreted_entry, address) \
- volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \
- nonstatic_field(ConstMethod, _constants, ConstantPool*) \
- nonstatic_field(ConstMethod, _stackmap_data, Array<u1>*) \
- nonstatic_field(ConstMethod, _constMethod_size, int) \
- nonstatic_field(ConstMethod, _flags, u2) \
- nonstatic_field(ConstMethod, _code_size, u2) \
- nonstatic_field(ConstMethod, _name_index, u2) \
- nonstatic_field(ConstMethod, _signature_index, u2) \
- nonstatic_field(ConstMethod, _method_idnum, u2) \
- nonstatic_field(ConstMethod, _max_stack, u2) \
- nonstatic_field(ConstMethod, _max_locals, u2) \
- nonstatic_field(ConstMethod, _size_of_parameters, u2) \
+ nonstatic_field(MethodData, _size, int) \
+ nonstatic_field(MethodData, _method, Method*) \
+ nonstatic_field(MethodData, _data_size, int) \
+ nonstatic_field(MethodData, _data[0], intptr_t) \
+ nonstatic_field(MethodData, _parameters_type_data_di, int) \
+ nonstatic_field(MethodData, _nof_decompiles, uint) \
+ nonstatic_field(MethodData, _nof_overflow_recompiles, uint) \
+ nonstatic_field(MethodData, _nof_overflow_traps, uint) \
+ nonstatic_field(MethodData, _trap_hist._array[0], u1) \
+ nonstatic_field(MethodData, _eflags, intx) \
+ nonstatic_field(MethodData, _arg_local, intx) \
+ nonstatic_field(MethodData, _arg_stack, intx) \
+ nonstatic_field(MethodData, _arg_returned, intx) \
+ nonstatic_field(MethodData, _tenure_traps, uint) \
+ nonstatic_field(MethodData, _invoke_mask, int) \
+ nonstatic_field(MethodData, _backedge_mask, int) \
+ nonstatic_field(DataLayout, _header._struct._tag, u1) \
+ nonstatic_field(DataLayout, _header._struct._flags, u1) \
+ nonstatic_field(DataLayout, _header._struct._bci, u2) \
+ nonstatic_field(DataLayout, _cells[0], intptr_t) \
+ nonstatic_field(MethodCounters, _nmethod_age, int) \
+ nonstatic_field(MethodCounters, _interpreter_invocation_limit, int) \
+ nonstatic_field(MethodCounters, _interpreter_backward_branch_limit, int) \
+ nonstatic_field(MethodCounters, _interpreter_profile_limit, int) \
+ nonstatic_field(MethodCounters, _invoke_mask, int) \
+ nonstatic_field(MethodCounters, _backedge_mask, int) \
+ nonstatic_field(MethodCounters, _interpreter_invocation_count, int) \
+ nonstatic_field(MethodCounters, _interpreter_throwout_count, u2) \
+ nonstatic_field(MethodCounters, _number_of_breakpoints, u2) \
+ nonstatic_field(MethodCounters, _invocation_counter, InvocationCounter) \
+ nonstatic_field(MethodCounters, _backedge_counter, InvocationCounter) \
+ nonstatic_field(Method, _constMethod, ConstMethod*) \
+ nonstatic_field(Method, _method_data, MethodData*) \
+ nonstatic_field(Method, _method_counters, MethodCounters*) \
+ nonstatic_field(Method, _access_flags, AccessFlags) \
+ nonstatic_field(Method, _vtable_index, int) \
+ nonstatic_field(Method, _method_size, u2) \
+ nonstatic_field(Method, _intrinsic_id, u1) \
+ nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \
+ volatile_nonstatic_field(Method, _code, nmethod*) \
+ nonstatic_field(Method, _i2i_entry, address) \
+ nonstatic_field(Method, _adapter, AdapterHandlerEntry*) \
+ volatile_nonstatic_field(Method, _from_compiled_entry, address) \
+ volatile_nonstatic_field(Method, _from_interpreted_entry, address) \
+ volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \
+ nonstatic_field(ConstMethod, _constants, ConstantPool*) \
+ nonstatic_field(ConstMethod, _stackmap_data, Array<u1>*) \
+ nonstatic_field(ConstMethod, _constMethod_size, int) \
+ nonstatic_field(ConstMethod, _flags, u2) \
+ nonstatic_field(ConstMethod, _code_size, u2) \
+ nonstatic_field(ConstMethod, _name_index, u2) \
+ nonstatic_field(ConstMethod, _signature_index, u2) \
+ nonstatic_field(ConstMethod, _method_idnum, u2) \
+ nonstatic_field(ConstMethod, _max_stack, u2) \
+ nonstatic_field(ConstMethod, _max_locals, u2) \
+ nonstatic_field(ConstMethod, _size_of_parameters, u2) \
nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \
nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \
volatile_nonstatic_field(Symbol, _refcount, short) \
@@ -414,10 +414,10 @@
/* Constant Pool Cache */ \
/***********************/ \
\
- volatile_nonstatic_field(ConstantPoolCacheEntry, _indices, intx) \
- nonstatic_field(ConstantPoolCacheEntry, _f1, volatile Metadata*) \
- volatile_nonstatic_field(ConstantPoolCacheEntry, _f2, intx) \
- volatile_nonstatic_field(ConstantPoolCacheEntry, _flags, intx) \
+ volatile_nonstatic_field(ConstantPoolCacheEntry, _indices, intx) \
+ nonstatic_field(ConstantPoolCacheEntry, _f1, volatile Metadata*) \
+ volatile_nonstatic_field(ConstantPoolCacheEntry, _f2, intx) \
+ volatile_nonstatic_field(ConstantPoolCacheEntry, _flags, intx) \
\
/********************************/ \
/* MethodOop-related structures */ \
@@ -631,83 +631,83 @@
/* SymbolTable */ \
/***************/ \
\
- static_field(SymbolTable, _the_table, SymbolTable*) \
- static_field(SymbolTable, _shared_table, SymbolCompactHashTable) \
+ static_field(SymbolTable, _the_table, SymbolTable*) \
+ static_field(SymbolTable, _shared_table, SymbolCompactHashTable) \
\
/***************/ \
/* StringTable */ \
/***************/ \
\
- static_field(StringTable, _the_table, StringTable*) \
+ static_field(StringTable, _the_table, StringTable*) \
\
/********************/ \
/* CompactHashTable */ \
/********************/ \
\
- nonstatic_field(SymbolCompactHashTable, _base_address, uintx) \
- nonstatic_field(SymbolCompactHashTable, _entry_count, juint) \
- nonstatic_field(SymbolCompactHashTable, _bucket_count, juint) \
- nonstatic_field(SymbolCompactHashTable, _table_end_offset, juint) \
- nonstatic_field(SymbolCompactHashTable, _buckets, juint*) \
+ nonstatic_field(SymbolCompactHashTable, _base_address, uintx) \
+ nonstatic_field(SymbolCompactHashTable, _entry_count, juint) \
+ nonstatic_field(SymbolCompactHashTable, _bucket_count, juint) \
+ nonstatic_field(SymbolCompactHashTable, _table_end_offset, juint) \
+ nonstatic_field(SymbolCompactHashTable, _buckets, juint*) \
\
/********************/ \
/* SystemDictionary */ \
/********************/ \
\
- static_field(SystemDictionary, _dictionary, Dictionary*) \
- static_field(SystemDictionary, _placeholders, PlaceholderTable*) \
- static_field(SystemDictionary, _shared_dictionary, Dictionary*) \
- static_field(SystemDictionary, _system_loader_lock_obj, oop) \
- static_field(SystemDictionary, _loader_constraints, LoaderConstraintTable*) \
- static_field(SystemDictionary, WK_KLASS(Object_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(String_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Class_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Cloneable_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(ClassLoader_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Serializable_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(System_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Throwable_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(ThreadDeath_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Error_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Exception_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(RuntimeException_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(ClassNotFoundException_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(NoClassDefFoundError_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(LinkageError_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(ClassCastException_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(ArrayStoreException_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(VirtualMachineError_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(OutOfMemoryError_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(SecureClassLoader_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Reference_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(SoftReference_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(FinalReference_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Cleaner_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Finalizer_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Thread_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(Properties_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), Klass*) \
- static_field(SystemDictionary, WK_KLASS(MethodHandle_klass), Klass*) \
- static_field(SystemDictionary, _box_klasses[0], Klass*) \
- static_field(SystemDictionary, _java_system_loader, oop) \
+ static_field(SystemDictionary, _dictionary, Dictionary*) \
+ static_field(SystemDictionary, _placeholders, PlaceholderTable*) \
+ static_field(SystemDictionary, _shared_dictionary, Dictionary*) \
+ static_field(SystemDictionary, _system_loader_lock_obj, oop) \
+ static_field(SystemDictionary, _loader_constraints, LoaderConstraintTable*) \
+ static_field(SystemDictionary, WK_KLASS(Object_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(String_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Class_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Cloneable_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(ClassLoader_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Serializable_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(System_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Throwable_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(ThreadDeath_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Error_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Exception_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(RuntimeException_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(ClassNotFoundException_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(NoClassDefFoundError_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(LinkageError_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(ClassCastException_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(ArrayStoreException_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(VirtualMachineError_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(OutOfMemoryError_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(SecureClassLoader_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Reference_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(SoftReference_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(FinalReference_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Cleaner_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Finalizer_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Thread_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Properties_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(MethodHandle_klass), Klass*) \
+ static_field(SystemDictionary, _box_klasses[0], Klass*) \
+ static_field(SystemDictionary, _java_system_loader, oop) \
\
/*************/ \
/* vmSymbols */ \
/*************/ \
\
- static_field(vmSymbols, _symbols[0], Symbol*) \
+ static_field(vmSymbols, _symbols[0], Symbol*) \
\
/*******************/ \
/* HashtableBucket */ \
/*******************/ \
\
- nonstatic_field(HashtableBucket<mtInternal>, _entry, BasicHashtableEntry<mtInternal>*) \
+ nonstatic_field(HashtableBucket<mtInternal>, _entry, BasicHashtableEntry<mtInternal>*) \
\
/******************/ \
/* HashtableEntry */ \
@@ -721,12 +721,12 @@
/* Hashtable */ \
/*************/ \
\
- nonstatic_field(BasicHashtable<mtInternal>, _table_size, int) \
- nonstatic_field(BasicHashtable<mtInternal>, _buckets, HashtableBucket<mtInternal>*) \
- nonstatic_field(BasicHashtable<mtInternal>, _free_list, BasicHashtableEntry<mtInternal>*) \
- nonstatic_field(BasicHashtable<mtInternal>, _first_free_entry, char*) \
- nonstatic_field(BasicHashtable<mtInternal>, _end_block, char*) \
- nonstatic_field(BasicHashtable<mtInternal>, _entry_size, int) \
+ nonstatic_field(BasicHashtable<mtInternal>, _table_size, int) \
+ nonstatic_field(BasicHashtable<mtInternal>, _buckets, HashtableBucket<mtInternal>*) \
+ nonstatic_field(BasicHashtable<mtInternal>, _free_list, BasicHashtableEntry<mtInternal>*) \
+ nonstatic_field(BasicHashtable<mtInternal>, _first_free_entry, char*) \
+ nonstatic_field(BasicHashtable<mtInternal>, _end_block, char*) \
+ nonstatic_field(BasicHashtable<mtInternal>, _entry_size, int) \
\
/*******************/ \
/* DictionaryEntry */ \
@@ -764,7 +764,7 @@
nonstatic_field(ClassLoaderData, _class_loader, oop) \
nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \
\
- static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \
+ static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \
\
/**********/ \
/* Arrays */ \
@@ -786,8 +786,8 @@
/* CodeCache (NOTE: incomplete) */ \
/********************************/ \
\
- static_field(CodeCache, _heaps, GrowableArray<CodeHeap*>*) \
- static_field(CodeCache, _scavenge_root_nmethods, nmethod*) \
+ static_field(CodeCache, _heaps, GrowableArray<CodeHeap*>*) \
+ static_field(CodeCache, _scavenge_root_nmethods, nmethod*) \
\
/*******************************/ \
/* CodeHeap (NOTE: incomplete) */ \
@@ -873,37 +873,37 @@
/* NMethods (NOTE: incomplete, but only a little) */ \
/**************************************************/ \
\
- nonstatic_field(nmethod, _method, Method*) \
- nonstatic_field(nmethod, _entry_bci, int) \
- nonstatic_field(nmethod, _osr_link, nmethod*) \
- nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \
- nonstatic_field(nmethod, _scavenge_root_state, jbyte) \
- nonstatic_field(nmethod, _state, volatile unsigned char) \
- nonstatic_field(nmethod, _exception_offset, int) \
- nonstatic_field(nmethod, _deoptimize_offset, int) \
- nonstatic_field(nmethod, _deoptimize_mh_offset, int) \
- nonstatic_field(nmethod, _orig_pc_offset, int) \
- nonstatic_field(nmethod, _stub_offset, int) \
- nonstatic_field(nmethod, _consts_offset, int) \
- nonstatic_field(nmethod, _oops_offset, int) \
- nonstatic_field(nmethod, _metadata_offset, int) \
- nonstatic_field(nmethod, _scopes_data_offset, int) \
- nonstatic_field(nmethod, _scopes_pcs_offset, int) \
- nonstatic_field(nmethod, _dependencies_offset, int) \
- nonstatic_field(nmethod, _handler_table_offset, int) \
- nonstatic_field(nmethod, _nul_chk_table_offset, int) \
- nonstatic_field(nmethod, _nmethod_end_offset, int) \
- nonstatic_field(nmethod, _entry_point, address) \
- nonstatic_field(nmethod, _verified_entry_point, address) \
- nonstatic_field(nmethod, _osr_entry_point, address) \
- volatile_nonstatic_field(nmethod, _lock_count, jint) \
- nonstatic_field(nmethod, _stack_traversal_mark, long) \
- nonstatic_field(nmethod, _compile_id, int) \
- nonstatic_field(nmethod, _comp_level, int) \
- nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \
- nonstatic_field(nmethod, _marked_for_deoptimization, bool) \
- \
- unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \
+ nonstatic_field(nmethod, _method, Method*) \
+ nonstatic_field(nmethod, _entry_bci, int) \
+ nonstatic_field(nmethod, _osr_link, nmethod*) \
+ nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \
+ nonstatic_field(nmethod, _scavenge_root_state, jbyte) \
+ nonstatic_field(nmethod, _state, volatile unsigned char) \
+ nonstatic_field(nmethod, _exception_offset, int) \
+ nonstatic_field(nmethod, _deoptimize_offset, int) \
+ nonstatic_field(nmethod, _deoptimize_mh_offset, int) \
+ nonstatic_field(nmethod, _orig_pc_offset, int) \
+ nonstatic_field(nmethod, _stub_offset, int) \
+ nonstatic_field(nmethod, _consts_offset, int) \
+ nonstatic_field(nmethod, _oops_offset, int) \
+ nonstatic_field(nmethod, _metadata_offset, int) \
+ nonstatic_field(nmethod, _scopes_data_offset, int) \
+ nonstatic_field(nmethod, _scopes_pcs_offset, int) \
+ nonstatic_field(nmethod, _dependencies_offset, int) \
+ nonstatic_field(nmethod, _handler_table_offset, int) \
+ nonstatic_field(nmethod, _nul_chk_table_offset, int) \
+ nonstatic_field(nmethod, _nmethod_end_offset, int) \
+ nonstatic_field(nmethod, _entry_point, address) \
+ nonstatic_field(nmethod, _verified_entry_point, address) \
+ nonstatic_field(nmethod, _osr_entry_point, address) \
+ volatile_nonstatic_field(nmethod, _lock_count, jint) \
+ nonstatic_field(nmethod, _stack_traversal_mark, long) \
+ nonstatic_field(nmethod, _compile_id, int) \
+ nonstatic_field(nmethod, _comp_level, int) \
+ nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \
+ nonstatic_field(nmethod, _marked_for_deoptimization, bool) \
+ \
+ unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \
\
/********************************/ \
/* JavaCalls (NOTE: incomplete) */ \
@@ -928,7 +928,7 @@
nonstatic_field(ThreadShadow, _pending_exception, oop) \
nonstatic_field(ThreadShadow, _exception_file, const char*) \
nonstatic_field(ThreadShadow, _exception_line, int) \
- volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \
+ volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \
nonstatic_field(Thread, _active_handles, JNIHandleBlock*) \
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
nonstatic_field(Thread, _allocated_bytes, jlong) \
@@ -948,7 +948,7 @@
volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \
nonstatic_field(JavaThread, _special_runtime_exit_condition, JavaThread::AsyncRequests) \
nonstatic_field(JavaThread, _saved_exception_pc, address) \
- volatile_nonstatic_field(JavaThread, _thread_state, JavaThreadState) \
+ volatile_nonstatic_field(JavaThread, _thread_state, JavaThreadState) \
nonstatic_field(JavaThread, _osthread, OSThread*) \
nonstatic_field(JavaThread, _stack_base, address) \
nonstatic_field(JavaThread, _stack_size, size_t) \
@@ -991,7 +991,7 @@
static_field(JNIHandles, _weak_global_handles, JNIHandleBlock*) \
static_field(JNIHandles, _deleted_handle, oop) \
\
- unchecked_nonstatic_field(JNIHandleBlock, _handles, JNIHandleBlock::block_size_in_oops * sizeof(Oop)) /* Note: no type */ \
+ unchecked_nonstatic_field(JNIHandleBlock, _handles, JNIHandleBlock::block_size_in_oops * sizeof(Oop)) /* Note: no type */ \
nonstatic_field(JNIHandleBlock, _top, int) \
nonstatic_field(JNIHandleBlock, _next, JNIHandleBlock*) \
\
@@ -1019,80 +1019,80 @@
/* allocation */ \
/**************/ \
\
- nonstatic_field(Chunk, _next, Chunk*) \
- nonstatic_field(Chunk, _len, const size_t) \
+ nonstatic_field(Chunk, _next, Chunk*) \
+ nonstatic_field(Chunk, _len, const size_t) \
\
- nonstatic_field(Arena, _first, Chunk*) \
- nonstatic_field(Arena, _chunk, Chunk*) \
- nonstatic_field(Arena, _hwm, char*) \
- nonstatic_field(Arena, _max, char*) \
+ nonstatic_field(Arena, _first, Chunk*) \
+ nonstatic_field(Arena, _chunk, Chunk*) \
+ nonstatic_field(Arena, _hwm, char*) \
+ nonstatic_field(Arena, _max, char*) \
\
/************/ \
/* CI */ \
/************/ \
\
- nonstatic_field(ciEnv, _system_dictionary_modification_counter, int) \
- nonstatic_field(ciEnv, _compiler_data, void*) \
- nonstatic_field(ciEnv, _failure_reason, const char*) \
- nonstatic_field(ciEnv, _factory, ciObjectFactory*) \
- nonstatic_field(ciEnv, _dependencies, Dependencies*) \
- nonstatic_field(ciEnv, _task, CompileTask*) \
- nonstatic_field(ciEnv, _arena, Arena*) \
+ nonstatic_field(ciEnv, _system_dictionary_modification_counter, int) \
+ nonstatic_field(ciEnv, _compiler_data, void*) \
+ nonstatic_field(ciEnv, _failure_reason, const char*) \
+ nonstatic_field(ciEnv, _factory, ciObjectFactory*) \
+ nonstatic_field(ciEnv, _dependencies, Dependencies*) \
+ nonstatic_field(ciEnv, _task, CompileTask*) \
+ nonstatic_field(ciEnv, _arena, Arena*) \
\
- nonstatic_field(ciBaseObject, _ident, uint) \
+ nonstatic_field(ciBaseObject, _ident, uint) \
\
- nonstatic_field(ciObject, _handle, jobject) \
- nonstatic_field(ciObject, _klass, ciKlass*) \
+ nonstatic_field(ciObject, _handle, jobject) \
+ nonstatic_field(ciObject, _klass, ciKlass*) \
\
- nonstatic_field(ciMetadata, _metadata, Metadata*) \
+ nonstatic_field(ciMetadata, _metadata, Metadata*) \
\
- nonstatic_field(ciSymbol, _symbol, Symbol*) \
+ nonstatic_field(ciSymbol, _symbol, Symbol*) \
\
- nonstatic_field(ciType, _basic_type, BasicType) \
+ nonstatic_field(ciType, _basic_type, BasicType) \
\
- nonstatic_field(ciKlass, _name, ciSymbol*) \
+ nonstatic_field(ciKlass, _name, ciSymbol*) \
\
- nonstatic_field(ciArrayKlass, _dimension, jint) \
+ nonstatic_field(ciArrayKlass, _dimension, jint) \
\
- nonstatic_field(ciObjArrayKlass, _element_klass, ciKlass*) \
- nonstatic_field(ciObjArrayKlass, _base_element_klass, ciKlass*) \
+ nonstatic_field(ciObjArrayKlass, _element_klass, ciKlass*) \
+ nonstatic_field(ciObjArrayKlass, _base_element_klass, ciKlass*) \
\
- nonstatic_field(ciInstanceKlass, _init_state, InstanceKlass::ClassState) \
- nonstatic_field(ciInstanceKlass, _is_shared, bool) \
+ nonstatic_field(ciInstanceKlass, _init_state, InstanceKlass::ClassState) \
+ nonstatic_field(ciInstanceKlass, _is_shared, bool) \
\
- nonstatic_field(ciMethod, _interpreter_invocation_count, int) \
- nonstatic_field(ciMethod, _interpreter_throwout_count, int) \
- nonstatic_field(ciMethod, _instructions_size, int) \
+ nonstatic_field(ciMethod, _interpreter_invocation_count, int) \
+ nonstatic_field(ciMethod, _interpreter_throwout_count, int) \
+ nonstatic_field(ciMethod, _instructions_size, int) \
\
- nonstatic_field(ciMethodData, _data_size, int) \
- nonstatic_field(ciMethodData, _state, u_char) \
- nonstatic_field(ciMethodData, _extra_data_size, int) \
- nonstatic_field(ciMethodData, _data, intptr_t*) \
- nonstatic_field(ciMethodData, _hint_di, int) \
- nonstatic_field(ciMethodData, _eflags, intx) \
- nonstatic_field(ciMethodData, _arg_local, intx) \
- nonstatic_field(ciMethodData, _arg_stack, intx) \
- nonstatic_field(ciMethodData, _arg_returned, intx) \
- nonstatic_field(ciMethodData, _current_mileage, int) \
- nonstatic_field(ciMethodData, _orig, MethodData) \
+ nonstatic_field(ciMethodData, _data_size, int) \
+ nonstatic_field(ciMethodData, _state, u_char) \
+ nonstatic_field(ciMethodData, _extra_data_size, int) \
+ nonstatic_field(ciMethodData, _data, intptr_t*) \
+ nonstatic_field(ciMethodData, _hint_di, int) \
+ nonstatic_field(ciMethodData, _eflags, intx) \
+ nonstatic_field(ciMethodData, _arg_local, intx) \
+ nonstatic_field(ciMethodData, _arg_stack, intx) \
+ nonstatic_field(ciMethodData, _arg_returned, intx) \
+ nonstatic_field(ciMethodData, _current_mileage, int) \
+ nonstatic_field(ciMethodData, _orig, MethodData) \
\
- nonstatic_field(ciField, _holder, ciInstanceKlass*) \
- nonstatic_field(ciField, _name, ciSymbol*) \
- nonstatic_field(ciField, _signature, ciSymbol*) \
- nonstatic_field(ciField, _offset, int) \
- nonstatic_field(ciField, _is_constant, bool) \
- nonstatic_field(ciField, _constant_value, ciConstant) \
+ nonstatic_field(ciField, _holder, ciInstanceKlass*) \
+ nonstatic_field(ciField, _name, ciSymbol*) \
+ nonstatic_field(ciField, _signature, ciSymbol*) \
+ nonstatic_field(ciField, _offset, int) \
+ nonstatic_field(ciField, _is_constant, bool) \
+ nonstatic_field(ciField, _constant_value, ciConstant) \
\
- nonstatic_field(ciObjectFactory, _ci_metadata, GrowableArray<ciMetadata*>*) \
- nonstatic_field(ciObjectFactory, _symbols, GrowableArray<ciSymbol*>*) \
- nonstatic_field(ciObjectFactory, _unloaded_methods, GrowableArray<ciMethod*>*) \
+ nonstatic_field(ciObjectFactory, _ci_metadata, GrowableArray<ciMetadata*>*) \
+ nonstatic_field(ciObjectFactory, _symbols, GrowableArray<ciSymbol*>*) \
+ nonstatic_field(ciObjectFactory, _unloaded_methods, GrowableArray<ciMethod*>*) \
\
- nonstatic_field(ciConstant, _type, BasicType) \
- nonstatic_field(ciConstant, _value._int, jint) \
- nonstatic_field(ciConstant, _value._long, jlong) \
- nonstatic_field(ciConstant, _value._float, jfloat) \
- nonstatic_field(ciConstant, _value._double, jdouble) \
- nonstatic_field(ciConstant, _value._object, ciObject*) \
+ nonstatic_field(ciConstant, _type, BasicType) \
+ nonstatic_field(ciConstant, _value._int, jint) \
+ nonstatic_field(ciConstant, _value._long, jlong) \
+ nonstatic_field(ciConstant, _value._float, jfloat) \
+ nonstatic_field(ciConstant, _value._double, jdouble) \
+ nonstatic_field(ciConstant, _value._object, ciObject*) \
\
/************/ \
/* Monitors */ \
@@ -1108,7 +1108,7 @@
volatile_nonstatic_field(BasicLock, _displaced_header, markOop) \
nonstatic_field(BasicObjectLock, _lock, BasicLock) \
nonstatic_field(BasicObjectLock, _obj, oop) \
- static_field(ObjectSynchronizer, gBlockList, ObjectMonitor*) \
+ static_field(ObjectSynchronizer, gBlockList, ObjectMonitor*) \
\
/*********************/ \
/* Matcher (C2 only) */ \
@@ -1116,111 +1116,111 @@
\
unchecked_c2_static_field(Matcher, _regEncode, sizeof(Matcher::_regEncode)) /* NOTE: no type */ \
\
- c2_nonstatic_field(Node, _in, Node**) \
- c2_nonstatic_field(Node, _out, Node**) \
- c2_nonstatic_field(Node, _cnt, node_idx_t) \
- c2_nonstatic_field(Node, _max, node_idx_t) \
- c2_nonstatic_field(Node, _outcnt, node_idx_t) \
- c2_nonstatic_field(Node, _outmax, node_idx_t) \
- c2_nonstatic_field(Node, _idx, const node_idx_t) \
- c2_nonstatic_field(Node, _class_id, jushort) \
- c2_nonstatic_field(Node, _flags, jushort) \
+ c2_nonstatic_field(Node, _in, Node**) \
+ c2_nonstatic_field(Node, _out, Node**) \
+ c2_nonstatic_field(Node, _cnt, node_idx_t) \
+ c2_nonstatic_field(Node, _max, node_idx_t) \
+ c2_nonstatic_field(Node, _outcnt, node_idx_t) \
+ c2_nonstatic_field(Node, _outmax, node_idx_t) \
+ c2_nonstatic_field(Node, _idx, const node_idx_t) \
+ c2_nonstatic_field(Node, _class_id, jushort) \
+ c2_nonstatic_field(Node, _flags, jushort) \
\
- c2_nonstatic_field(Compile, _root, RootNode*) \
- c2_nonstatic_field(Compile, _unique, uint) \
- c2_nonstatic_field(Compile, _entry_bci, int) \
- c2_nonstatic_field(Compile, _top, Node*) \
- c2_nonstatic_field(Compile, _cfg, PhaseCFG*) \
- c2_nonstatic_field(Compile, _regalloc, PhaseRegAlloc*) \
- c2_nonstatic_field(Compile, _method, ciMethod*) \
- c2_nonstatic_field(Compile, _compile_id, const int) \
- c2_nonstatic_field(Compile, _save_argument_registers, const bool) \
- c2_nonstatic_field(Compile, _subsume_loads, const bool) \
- c2_nonstatic_field(Compile, _do_escape_analysis, const bool) \
- c2_nonstatic_field(Compile, _eliminate_boxing, const bool) \
- c2_nonstatic_field(Compile, _ilt, InlineTree*) \
+ c2_nonstatic_field(Compile, _root, RootNode*) \
+ c2_nonstatic_field(Compile, _unique, uint) \
+ c2_nonstatic_field(Compile, _entry_bci, int) \
+ c2_nonstatic_field(Compile, _top, Node*) \
+ c2_nonstatic_field(Compile, _cfg, PhaseCFG*) \
+ c2_nonstatic_field(Compile, _regalloc, PhaseRegAlloc*) \
+ c2_nonstatic_field(Compile, _method, ciMethod*) \
+ c2_nonstatic_field(Compile, _compile_id, const int) \
+ c2_nonstatic_field(Compile, _save_argument_registers, const bool) \
+ c2_nonstatic_field(Compile, _subsume_loads, const bool) \
+ c2_nonstatic_field(Compile, _do_escape_analysis, const bool) \
+ c2_nonstatic_field(Compile, _eliminate_boxing, const bool) \
+ c2_nonstatic_field(Compile, _ilt, InlineTree*) \
\
- c2_nonstatic_field(InlineTree, _caller_jvms, JVMState*) \
- c2_nonstatic_field(InlineTree, _method, ciMethod*) \
- c2_nonstatic_field(InlineTree, _caller_tree, InlineTree*) \
- c2_nonstatic_field(InlineTree, _subtrees, GrowableArray<InlineTree*>) \
+ c2_nonstatic_field(InlineTree, _caller_jvms, JVMState*) \
+ c2_nonstatic_field(InlineTree, _method, ciMethod*) \
+ c2_nonstatic_field(InlineTree, _caller_tree, InlineTree*) \
+ c2_nonstatic_field(InlineTree, _subtrees, GrowableArray<InlineTree*>) \
\
- c2_nonstatic_field(OptoRegPair, _first, short) \
- c2_nonstatic_field(OptoRegPair, _second, short) \
+ c2_nonstatic_field(OptoRegPair, _first, short) \
+ c2_nonstatic_field(OptoRegPair, _second, short) \
\
- c2_nonstatic_field(JVMState, _caller, JVMState*) \
- c2_nonstatic_field(JVMState, _depth, uint) \
- c2_nonstatic_field(JVMState, _locoff, uint) \
- c2_nonstatic_field(JVMState, _stkoff, uint) \
- c2_nonstatic_field(JVMState, _monoff, uint) \
- c2_nonstatic_field(JVMState, _scloff, uint) \
- c2_nonstatic_field(JVMState, _endoff, uint) \
- c2_nonstatic_field(JVMState, _sp, uint) \
- c2_nonstatic_field(JVMState, _bci, int) \
- c2_nonstatic_field(JVMState, _method, ciMethod*) \
- c2_nonstatic_field(JVMState, _map, SafePointNode*) \
+ c2_nonstatic_field(JVMState, _caller, JVMState*) \
+ c2_nonstatic_field(JVMState, _depth, uint) \
+ c2_nonstatic_field(JVMState, _locoff, uint) \
+ c2_nonstatic_field(JVMState, _stkoff, uint) \
+ c2_nonstatic_field(JVMState, _monoff, uint) \
+ c2_nonstatic_field(JVMState, _scloff, uint) \
+ c2_nonstatic_field(JVMState, _endoff, uint) \
+ c2_nonstatic_field(JVMState, _sp, uint) \
+ c2_nonstatic_field(JVMState, _bci, int) \
+ c2_nonstatic_field(JVMState, _method, ciMethod*) \
+ c2_nonstatic_field(JVMState, _map, SafePointNode*) \
\
- c2_nonstatic_field(SafePointNode, _jvms, JVMState* const) \
+ c2_nonstatic_field(SafePointNode, _jvms, JVMState* const) \
\
- c2_nonstatic_field(MachSafePointNode, _jvms, JVMState*) \
- c2_nonstatic_field(MachSafePointNode, _jvmadj, uint) \
+ c2_nonstatic_field(MachSafePointNode, _jvms, JVMState*) \
+ c2_nonstatic_field(MachSafePointNode, _jvmadj, uint) \
\
- c2_nonstatic_field(MachIfNode, _prob, jfloat) \
- c2_nonstatic_field(MachIfNode, _fcnt, jfloat) \
+ c2_nonstatic_field(MachIfNode, _prob, jfloat) \
+ c2_nonstatic_field(MachIfNode, _fcnt, jfloat) \
\
- c2_nonstatic_field(CallNode, _entry_point, address) \
+ c2_nonstatic_field(CallNode, _entry_point, address) \
\
- c2_nonstatic_field(CallJavaNode, _method, ciMethod*) \
+ c2_nonstatic_field(CallJavaNode, _method, ciMethod*) \
\
- c2_nonstatic_field(CallRuntimeNode, _name, const char*) \
+ c2_nonstatic_field(CallRuntimeNode, _name, const char*) \
\
- c2_nonstatic_field(CallStaticJavaNode, _name, const char*) \
+ c2_nonstatic_field(CallStaticJavaNode, _name, const char*) \
\
- c2_nonstatic_field(MachCallJavaNode, _method, ciMethod*) \
- c2_nonstatic_field(MachCallJavaNode, _bci, int) \
+ c2_nonstatic_field(MachCallJavaNode, _method, ciMethod*) \
+ c2_nonstatic_field(MachCallJavaNode, _bci, int) \
\
- c2_nonstatic_field(MachCallStaticJavaNode, _name, const char*) \
+ c2_nonstatic_field(MachCallStaticJavaNode, _name, const char*) \
\
- c2_nonstatic_field(MachCallRuntimeNode, _name, const char*) \
+ c2_nonstatic_field(MachCallRuntimeNode, _name, const char*) \
\
- c2_nonstatic_field(PhaseCFG, _number_of_blocks, uint) \
- c2_nonstatic_field(PhaseCFG, _blocks, Block_List) \
- c2_nonstatic_field(PhaseCFG, _node_to_block_mapping, Block_Array) \
- c2_nonstatic_field(PhaseCFG, _root_block, Block*) \
+ c2_nonstatic_field(PhaseCFG, _number_of_blocks, uint) \
+ c2_nonstatic_field(PhaseCFG, _blocks, Block_List) \
+ c2_nonstatic_field(PhaseCFG, _node_to_block_mapping, Block_Array) \
+ c2_nonstatic_field(PhaseCFG, _root_block, Block*) \
\
- c2_nonstatic_field(PhaseRegAlloc, _node_regs, OptoRegPair*) \
- c2_nonstatic_field(PhaseRegAlloc, _node_regs_max_index, uint) \
- c2_nonstatic_field(PhaseRegAlloc, _framesize, uint) \
- c2_nonstatic_field(PhaseRegAlloc, _max_reg, OptoReg::Name) \
+ c2_nonstatic_field(PhaseRegAlloc, _node_regs, OptoRegPair*) \
+ c2_nonstatic_field(PhaseRegAlloc, _node_regs_max_index, uint) \
+ c2_nonstatic_field(PhaseRegAlloc, _framesize, uint) \
+ c2_nonstatic_field(PhaseRegAlloc, _max_reg, OptoReg::Name) \
\
- c2_nonstatic_field(PhaseChaitin, _trip_cnt, int) \
- c2_nonstatic_field(PhaseChaitin, _alternate, int) \
- c2_nonstatic_field(PhaseChaitin, _lo_degree, uint) \
- c2_nonstatic_field(PhaseChaitin, _lo_stk_degree, uint) \
- c2_nonstatic_field(PhaseChaitin, _hi_degree, uint) \
- c2_nonstatic_field(PhaseChaitin, _simplified, uint) \
+ c2_nonstatic_field(PhaseChaitin, _trip_cnt, int) \
+ c2_nonstatic_field(PhaseChaitin, _alternate, int) \
+ c2_nonstatic_field(PhaseChaitin, _lo_degree, uint) \
+ c2_nonstatic_field(PhaseChaitin, _lo_stk_degree, uint) \
+ c2_nonstatic_field(PhaseChaitin, _hi_degree, uint) \
+ c2_nonstatic_field(PhaseChaitin, _simplified, uint) \
\
- c2_nonstatic_field(Block, _nodes, Node_List) \
- c2_nonstatic_field(Block, _succs, Block_Array) \
- c2_nonstatic_field(Block, _num_succs, uint) \
- c2_nonstatic_field(Block, _pre_order, uint) \
- c2_nonstatic_field(Block, _dom_depth, uint) \
- c2_nonstatic_field(Block, _idom, Block*) \
- c2_nonstatic_field(Block, _freq, jdouble) \
+ c2_nonstatic_field(Block, _nodes, Node_List) \
+ c2_nonstatic_field(Block, _succs, Block_Array) \
+ c2_nonstatic_field(Block, _num_succs, uint) \
+ c2_nonstatic_field(Block, _pre_order, uint) \
+ c2_nonstatic_field(Block, _dom_depth, uint) \
+ c2_nonstatic_field(Block, _idom, Block*) \
+ c2_nonstatic_field(Block, _freq, jdouble) \
\
- c2_nonstatic_field(CFGElement, _freq, jdouble) \
+ c2_nonstatic_field(CFGElement, _freq, jdouble) \
\
- c2_nonstatic_field(Block_List, _cnt, uint) \
+ c2_nonstatic_field(Block_List, _cnt, uint) \
\
- c2_nonstatic_field(Block_Array, _size, uint) \
- c2_nonstatic_field(Block_Array, _blocks, Block**) \
- c2_nonstatic_field(Block_Array, _arena, Arena*) \
+ c2_nonstatic_field(Block_Array, _size, uint) \
+ c2_nonstatic_field(Block_Array, _blocks, Block**) \
+ c2_nonstatic_field(Block_Array, _arena, Arena*) \
\
- c2_nonstatic_field(Node_List, _cnt, uint) \
+ c2_nonstatic_field(Node_List, _cnt, uint) \
\
- c2_nonstatic_field(Node_Array, _max, uint) \
- c2_nonstatic_field(Node_Array, _nodes, Node**) \
- c2_nonstatic_field(Node_Array, _a, Arena*) \
+ c2_nonstatic_field(Node_Array, _max, uint) \
+ c2_nonstatic_field(Node_Array, _nodes, Node**) \
+ c2_nonstatic_field(Node_Array, _a, Arena*) \
\
\
/*********************/ \
@@ -1231,22 +1231,22 @@
nonstatic_field(Flag, _name, const char*) \
unchecked_nonstatic_field(Flag, _addr, sizeof(void*)) /* NOTE: no type */ \
nonstatic_field(Flag, _flags, Flag::Flags) \
- static_field(Flag, flags, Flag*) \
- static_field(Flag, numFlags, size_t) \
+ static_field(Flag, flags, Flag*) \
+ static_field(Flag, numFlags, size_t) \
\
/*************************/ \
/* JDK / VM version info */ \
/*************************/ \
\
- static_field(Abstract_VM_Version, _s_vm_release, const char*) \
- static_field(Abstract_VM_Version, _s_internal_vm_info_string, const char*) \
- static_field(Abstract_VM_Version, _vm_major_version, int) \
- static_field(Abstract_VM_Version, _vm_minor_version, int) \
- static_field(Abstract_VM_Version, _vm_micro_version, int) \
- static_field(Abstract_VM_Version, _vm_build_number, int) \
- static_field(Abstract_VM_Version, _reserve_for_allocation_prefetch, int) \
+ static_field(Abstract_VM_Version, _s_vm_release, const char*) \
+ static_field(Abstract_VM_Version, _s_internal_vm_info_string, const char*) \
+ static_field(Abstract_VM_Version, _vm_major_version, int) \
+ static_field(Abstract_VM_Version, _vm_minor_version, int) \
+ static_field(Abstract_VM_Version, _vm_micro_version, int) \
+ static_field(Abstract_VM_Version, _vm_build_number, int) \
+ static_field(Abstract_VM_Version, _reserve_for_allocation_prefetch, int) \
\
- static_field(JDK_Version, _current, JDK_Version) \
+ static_field(JDK_Version, _current, JDK_Version) \
nonstatic_field(JDK_Version, _partially_initialized, bool) \
nonstatic_field(JDK_Version, _major, unsigned char) \
\
@@ -1260,65 +1260,65 @@
/* Arguments */ \
/*************/ \
\
- static_field(Arguments, _jvm_flags_array, char**) \
- static_field(Arguments, _num_jvm_flags, int) \
- static_field(Arguments, _jvm_args_array, char**) \
- static_field(Arguments, _num_jvm_args, int) \
- static_field(Arguments, _java_command, char*) \
+ static_field(Arguments, _jvm_flags_array, char**) \
+ static_field(Arguments, _num_jvm_flags, int) \
+ static_field(Arguments, _jvm_args_array, char**) \
+ static_field(Arguments, _num_jvm_args, int) \
+ static_field(Arguments, _java_command, char*) \
\
/************/ \
/* Array<T> */ \
/************/ \
\
- nonstatic_field(Array<int>, _length, int) \
- unchecked_nonstatic_field(Array<int>, _data, sizeof(int)) \
- unchecked_nonstatic_field(Array<u1>, _data, sizeof(u1)) \
- unchecked_nonstatic_field(Array<u2>, _data, sizeof(u2)) \
- unchecked_nonstatic_field(Array<Method*>, _data, sizeof(Method*)) \
- unchecked_nonstatic_field(Array<Klass*>, _data, sizeof(Klass*)) \
+ nonstatic_field(Array<int>, _length, int) \
+ unchecked_nonstatic_field(Array<int>, _data, sizeof(int)) \
+ unchecked_nonstatic_field(Array<u1>, _data, sizeof(u1)) \
+ unchecked_nonstatic_field(Array<u2>, _data, sizeof(u2)) \
+ unchecked_nonstatic_field(Array<Method*>, _data, sizeof(Method*)) \
+ unchecked_nonstatic_field(Array<Klass*>, _data, sizeof(Klass*)) \
\
/*********************************/ \
/* java_lang_Class fields */ \
/*********************************/ \
\
- static_field(java_lang_Class, _klass_offset, int) \
- static_field(java_lang_Class, _array_klass_offset, int) \
- static_field(java_lang_Class, _oop_size_offset, int) \
- static_field(java_lang_Class, _static_oop_field_count_offset, int) \
+ static_field(java_lang_Class, _klass_offset, int) \
+ static_field(java_lang_Class, _array_klass_offset, int) \
+ static_field(java_lang_Class, _oop_size_offset, int) \
+ static_field(java_lang_Class, _static_oop_field_count_offset, int) \
\
/************************/ \
/* Miscellaneous fields */ \
/************************/ \
\
- nonstatic_field(CompileTask, _method, Method*) \
- nonstatic_field(CompileTask, _osr_bci, int) \
- nonstatic_field(CompileTask, _comp_level, int) \
- nonstatic_field(CompileTask, _compile_id, uint) \
- nonstatic_field(CompileTask, _next, CompileTask*) \
- nonstatic_field(CompileTask, _prev, CompileTask*) \
+ nonstatic_field(CompileTask, _method, Method*) \
+ nonstatic_field(CompileTask, _osr_bci, int) \
+ nonstatic_field(CompileTask, _comp_level, int) \
+ nonstatic_field(CompileTask, _compile_id, uint) \
+ nonstatic_field(CompileTask, _next, CompileTask*) \
+ nonstatic_field(CompileTask, _prev, CompileTask*) \
\
- nonstatic_field(vframeArray, _next, vframeArray*) \
- nonstatic_field(vframeArray, _original, frame) \
- nonstatic_field(vframeArray, _caller, frame) \
- nonstatic_field(vframeArray, _frames, int) \
+ nonstatic_field(vframeArray, _next, vframeArray*) \
+ nonstatic_field(vframeArray, _original, frame) \
+ nonstatic_field(vframeArray, _caller, frame) \
+ nonstatic_field(vframeArray, _frames, int) \
\
- nonstatic_field(vframeArrayElement, _frame, frame) \
- nonstatic_field(vframeArrayElement, _bci, int) \
- nonstatic_field(vframeArrayElement, _method, Method*) \
+ nonstatic_field(vframeArrayElement, _frame, frame) \
+ nonstatic_field(vframeArrayElement, _bci, int) \
+ nonstatic_field(vframeArrayElement, _method, Method*) \
\
- nonstatic_field(PtrQueue, _active, bool) \
- nonstatic_field(PtrQueue, _buf, void**) \
- nonstatic_field(PtrQueue, _index, size_t) \
+ nonstatic_field(PtrQueue, _active, bool) \
+ nonstatic_field(PtrQueue, _buf, void**) \
+ nonstatic_field(PtrQueue, _index, size_t) \
\
- nonstatic_field(AccessFlags, _flags, jint) \
- nonstatic_field(elapsedTimer, _counter, jlong) \
- nonstatic_field(elapsedTimer, _active, bool) \
- nonstatic_field(InvocationCounter, _counter, unsigned int) \
- volatile_nonstatic_field(FreeChunk, _size, size_t) \
- nonstatic_field(FreeChunk, _next, FreeChunk*) \
- nonstatic_field(FreeChunk, _prev, FreeChunk*) \
- nonstatic_field(AdaptiveFreeList<FreeChunk>, _size, size_t) \
- nonstatic_field(AdaptiveFreeList<FreeChunk>, _count, ssize_t)
+ nonstatic_field(AccessFlags, _flags, jint) \
+ nonstatic_field(elapsedTimer, _counter, jlong) \
+ nonstatic_field(elapsedTimer, _active, bool) \
+ nonstatic_field(InvocationCounter, _counter, unsigned int) \
+ volatile_nonstatic_field(FreeChunk, _size, size_t) \
+ nonstatic_field(FreeChunk, _next, FreeChunk*) \
+ nonstatic_field(FreeChunk, _prev, FreeChunk*) \
+ nonstatic_field(AdaptiveFreeList<FreeChunk>, _size, size_t) \
+ nonstatic_field(AdaptiveFreeList<FreeChunk>, _count, ssize_t)
//--------------------------------------------------------------------------------
@@ -2253,6 +2253,7 @@
\
declare_constant(BarrierSet::ModRef) \
declare_constant(BarrierSet::CardTableModRef) \
+ declare_constant(BarrierSet::CardTableForRS) \
declare_constant(BarrierSet::CardTableExtension) \
declare_constant(BarrierSet::G1SATBCT) \
declare_constant(BarrierSet::G1SATBCTLogging) \
--- a/hotspot/src/share/vm/services/memoryPool.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/services/memoryPool.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -204,21 +204,21 @@
return MemoryUsage(initial_size(), used, committed, maxSize);
}
-SurvivorContiguousSpacePool::SurvivorContiguousSpacePool(DefNewGeneration* gen,
+SurvivorContiguousSpacePool::SurvivorContiguousSpacePool(DefNewGeneration* young_gen,
const char* name,
PoolType type,
size_t max_size,
bool support_usage_threshold) :
- CollectedMemoryPool(name, type, gen->from()->capacity(), max_size,
- support_usage_threshold), _gen(gen) {
+ CollectedMemoryPool(name, type, young_gen->from()->capacity(), max_size,
+ support_usage_threshold), _young_gen(young_gen) {
}
size_t SurvivorContiguousSpacePool::used_in_bytes() {
- return _gen->from()->used();
+ return _young_gen->from()->used();
}
size_t SurvivorContiguousSpacePool::committed_in_bytes() {
- return _gen->from()->capacity();
+ return _young_gen->from()->capacity();
}
MemoryUsage SurvivorContiguousSpacePool::get_memory_usage() {
--- a/hotspot/src/share/vm/services/memoryPool.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/services/memoryPool.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -163,10 +163,10 @@
class SurvivorContiguousSpacePool : public CollectedMemoryPool {
private:
- DefNewGeneration* _gen;
+ DefNewGeneration* _young_gen;
public:
- SurvivorContiguousSpacePool(DefNewGeneration* gen,
+ SurvivorContiguousSpacePool(DefNewGeneration* young_gen,
const char* name,
PoolType type,
size_t max_size,
--- a/hotspot/src/share/vm/services/memoryService.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/services/memoryService.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -212,13 +212,13 @@
return (MemoryPool*) pool;
}
-MemoryPool* MemoryService::add_survivor_spaces(DefNewGeneration* gen,
+MemoryPool* MemoryService::add_survivor_spaces(DefNewGeneration* young_gen,
const char* name,
bool is_heap,
size_t max_size,
bool support_usage_threshold) {
MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);
- SurvivorContiguousSpacePool* pool = new SurvivorContiguousSpacePool(gen, name, type, max_size, support_usage_threshold);
+ SurvivorContiguousSpacePool* pool = new SurvivorContiguousSpacePool(young_gen, name, type, max_size, support_usage_threshold);
_pools_list->append(pool);
return (MemoryPool*) pool;
@@ -328,18 +328,18 @@
#if INCLUDE_ALL_GCS
-void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) {
+void MemoryService::add_psYoung_memory_pool(PSYoungGen* young_gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) {
assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");
// Add a memory pool for each space and young gen doesn't
// support low memory detection as it is expected to get filled up.
- EdenMutableSpacePool* eden = new EdenMutableSpacePool(gen,
- gen->eden_space(),
+ EdenMutableSpacePool* eden = new EdenMutableSpacePool(young_gen,
+ young_gen->eden_space(),
"PS Eden Space",
MemoryPool::Heap,
false /* support_usage_threshold */);
- SurvivorMutableSpacePool* survivor = new SurvivorMutableSpacePool(gen,
+ SurvivorMutableSpacePool* survivor = new SurvivorMutableSpacePool(young_gen,
"PS Survivor Space",
MemoryPool::Heap,
false /* support_usage_threshold */);
@@ -352,13 +352,13 @@
_pools_list->append(survivor);
}
-void MemoryService::add_psOld_memory_pool(PSOldGen* gen, MemoryManager* mgr) {
- PSGenerationPool* old_gen = new PSGenerationPool(gen,
- "PS Old Gen",
- MemoryPool::Heap,
- true /* support_usage_threshold */);
- mgr->add_pool(old_gen);
- _pools_list->append(old_gen);
+void MemoryService::add_psOld_memory_pool(PSOldGen* old_gen, MemoryManager* mgr) {
+ PSGenerationPool* old_gen_pool = new PSGenerationPool(old_gen,
+ "PS Old Gen",
+ MemoryPool::Heap,
+ true /* support_usage_threshold */);
+ mgr->add_pool(old_gen_pool);
+ _pools_list->append(old_gen_pool);
}
void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
@@ -548,7 +548,7 @@
}
//
// GC manager type depends on the type of Generation. Depending on the space
-// availablity and vm options the gc uses major gc manager or minor gc
+// availability and vm options the gc uses major gc manager or minor gc
// manager or both. The type of gc manager depends on the generation kind.
// For DefNew and ParNew generation doing scavenge gc uses minor gc manager (so
// _fullGC is set to false ) and for other generation kinds doing
--- a/hotspot/src/share/vm/services/memoryService.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/services/memoryService.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -80,10 +80,10 @@
}
- static void add_psYoung_memory_pool(PSYoungGen* gen,
+ static void add_psYoung_memory_pool(PSYoungGen* young_gen,
MemoryManager* major_mgr,
MemoryManager* minor_mgr);
- static void add_psOld_memory_pool(PSOldGen* gen,
+ static void add_psOld_memory_pool(PSOldGen* old_gen,
MemoryManager* mgr);
static void add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
@@ -97,7 +97,7 @@
bool is_heap,
size_t max_size,
bool support_usage_threshold);
- static MemoryPool* add_survivor_spaces(DefNewGeneration* gen,
+ static MemoryPool* add_survivor_spaces(DefNewGeneration* young_gen,
const char* name,
bool is_heap,
size_t max_size,
@@ -162,7 +162,6 @@
bool recordGCEndTime, bool countCollection,
GCCause::Cause cause);
-
static void oops_do(OopClosure* f);
static bool get_verbose() { return PrintGC; }
--- a/hotspot/src/share/vm/services/psMemoryPool.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/services/psMemoryPool.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,18 +33,18 @@
#include "services/memoryManager.hpp"
#include "services/psMemoryPool.hpp"
-PSGenerationPool::PSGenerationPool(PSOldGen* gen,
+PSGenerationPool::PSGenerationPool(PSOldGen* old_gen,
const char* name,
PoolType type,
bool support_usage_threshold) :
- CollectedMemoryPool(name, type, gen->capacity_in_bytes(),
- gen->reserved().byte_size(), support_usage_threshold), _gen(gen) {
+ CollectedMemoryPool(name, type, old_gen->capacity_in_bytes(),
+ old_gen->reserved().byte_size(), support_usage_threshold), _old_gen(old_gen) {
}
MemoryUsage PSGenerationPool::get_memory_usage() {
size_t maxSize = (available_for_allocation() ? max_size() : 0);
size_t used = used_in_bytes();
- size_t committed = _gen->capacity_in_bytes();
+ size_t committed = _old_gen->capacity_in_bytes();
return MemoryUsage(initial_size(), used, committed, maxSize);
}
@@ -55,15 +55,16 @@
// Max size of PS eden space is changing due to ergonomic.
// PSYoungGen, PSOldGen, Eden, Survivor spaces are all resizable.
//
-EdenMutableSpacePool::EdenMutableSpacePool(PSYoungGen* gen,
+EdenMutableSpacePool::EdenMutableSpacePool(PSYoungGen* young_gen,
MutableSpace* space,
const char* name,
PoolType type,
bool support_usage_threshold) :
CollectedMemoryPool(name, type, space->capacity_in_bytes(),
- (gen->max_size() - gen->from_space()->capacity_in_bytes() - gen->to_space()->capacity_in_bytes()),
+ (young_gen->max_size() - young_gen->from_space()->capacity_in_bytes() - young_gen->to_space()->capacity_in_bytes()),
support_usage_threshold),
- _gen(gen), _space(space) {
+ _young_gen(young_gen),
+ _space(space) {
}
MemoryUsage EdenMutableSpacePool::get_memory_usage() {
@@ -79,13 +80,13 @@
//
// PS from and to survivor spaces could have different sizes.
//
-SurvivorMutableSpacePool::SurvivorMutableSpacePool(PSYoungGen* gen,
+SurvivorMutableSpacePool::SurvivorMutableSpacePool(PSYoungGen* young_gen,
const char* name,
PoolType type,
bool support_usage_threshold) :
- CollectedMemoryPool(name, type, gen->from_space()->capacity_in_bytes(),
- gen->from_space()->capacity_in_bytes(),
- support_usage_threshold), _gen(gen) {
+ CollectedMemoryPool(name, type, young_gen->from_space()->capacity_in_bytes(),
+ young_gen->from_space()->capacity_in_bytes(),
+ support_usage_threshold), _young_gen(young_gen) {
}
MemoryUsage SurvivorMutableSpacePool::get_memory_usage() {
--- a/hotspot/src/share/vm/services/psMemoryPool.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/services/psMemoryPool.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -39,23 +39,23 @@
class PSGenerationPool : public CollectedMemoryPool {
private:
- PSOldGen* _gen;
+ PSOldGen* _old_gen;
public:
PSGenerationPool(PSOldGen* pool, const char* name, PoolType type, bool support_usage_threshold);
MemoryUsage get_memory_usage();
- size_t used_in_bytes() { return _gen->used_in_bytes(); }
- size_t max_size() const { return _gen->reserved().byte_size(); }
+ size_t used_in_bytes() { return _old_gen->used_in_bytes(); }
+ size_t max_size() const { return _old_gen->reserved().byte_size(); }
};
class EdenMutableSpacePool : public CollectedMemoryPool {
private:
- PSYoungGen* _gen;
+ PSYoungGen* _young_gen;
MutableSpace* _space;
public:
- EdenMutableSpacePool(PSYoungGen* gen,
+ EdenMutableSpacePool(PSYoungGen* young_gen,
MutableSpace* space,
const char* name,
PoolType type,
@@ -66,16 +66,16 @@
size_t used_in_bytes() { return space()->used_in_bytes(); }
size_t max_size() const {
// Eden's max_size = max_size of Young Gen - the current committed size of survivor spaces
- return _gen->max_size() - _gen->from_space()->capacity_in_bytes() - _gen->to_space()->capacity_in_bytes();
+ return _young_gen->max_size() - _young_gen->from_space()->capacity_in_bytes() - _young_gen->to_space()->capacity_in_bytes();
}
};
class SurvivorMutableSpacePool : public CollectedMemoryPool {
private:
- PSYoungGen* _gen;
+ PSYoungGen* _young_gen;
public:
- SurvivorMutableSpacePool(PSYoungGen* gen,
+ SurvivorMutableSpacePool(PSYoungGen* young_gen,
const char* name,
PoolType type,
bool support_usage_threshold);
@@ -83,14 +83,14 @@
MemoryUsage get_memory_usage();
size_t used_in_bytes() {
- return _gen->from_space()->used_in_bytes();
+ return _young_gen->from_space()->used_in_bytes();
}
size_t committed_in_bytes() {
- return _gen->from_space()->capacity_in_bytes();
+ return _young_gen->from_space()->capacity_in_bytes();
}
size_t max_size() const {
// Return current committed size of the from-space
- return _gen->from_space()->capacity_in_bytes();
+ return _young_gen->from_space()->capacity_in_bytes();
}
};
--- a/hotspot/src/share/vm/shark/sharkBuilder.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -440,8 +440,10 @@
// HotSpot memory barriers
void SharkBuilder::CreateUpdateBarrierSet(BarrierSet* bs, Value* field) {
- if (bs->kind() != BarrierSet::CardTableModRef)
+ if (bs->kind() != BarrierSet::CardTableForRS &&
+ bs->kind() != BarrierSet::CardTableExtension) {
Unimplemented();
+ }
CreateStore(
LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card_val()),
--- a/hotspot/src/share/vm/utilities/endian.cpp Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "utilities/endian.hpp"
-#include "utilities/bytes.hpp"
-
-#ifndef bswap_16
-extern "C" inline u2 bswap_16(u2 x) {
- return ((x & 0xFF) << 8) |
- ((x >> 8) & 0xFF);
-}
-#endif
-
-#ifndef bswap_32
-extern "C" inline u4 bswap_32(u4 x) {
- return ((x & 0xFF) << 24) |
- ((x & 0xFF00) << 8) |
- ((x >> 8) & 0xFF00) |
- ((x >> 24) & 0xFF);
-}
-#endif
-
-#ifndef bswap_64
-extern "C" inline u8 bswap_64(u8 x) {
- return (u8)bswap_32((u4)x) << 32 |
- (u8)bswap_32((u4)(x >> 32));
-}
-#endif
-
-u2 NativeEndian::get(u2 x) { return x; }
-u4 NativeEndian::get(u4 x) { return x; }
-u8 NativeEndian::get(u8 x) { return x; }
-s2 NativeEndian::get(s2 x) { return x; }
-s4 NativeEndian::get(s4 x) { return x; }
-s8 NativeEndian::get(s8 x) { return x; }
-
-void NativeEndian::set(u2& x, u2 y) { x = y; }
-void NativeEndian::set(u4& x, u4 y) { x = y; }
-void NativeEndian::set(u8& x, u8 y) { x = y; }
-void NativeEndian::set(s2& x, s2 y) { x = y; }
-void NativeEndian::set(s4& x, s4 y) { x = y; }
-void NativeEndian::set(s8& x, s8 y) { x = y; }
-
-NativeEndian NativeEndian::_native;
-
-u2 SwappingEndian::get(u2 x) { return bswap_16(x); }
-u4 SwappingEndian::get(u4 x) { return bswap_32(x); }
-u8 SwappingEndian::get(u8 x) { return bswap_64(x); }
-s2 SwappingEndian::get(s2 x) { return bswap_16(x); }
-s4 SwappingEndian::get(s4 x) { return bswap_32(x); }
-s8 SwappingEndian::get(s8 x) { return bswap_64(x); }
-
-void SwappingEndian::set(u2& x, u2 y) { x = bswap_16(y); }
-void SwappingEndian::set(u4& x, u4 y) { x = bswap_32(y); }
-void SwappingEndian::set(u8& x, u8 y) { x = bswap_64(y); }
-void SwappingEndian::set(s2& x, s2 y) { x = bswap_16(y); }
-void SwappingEndian::set(s4& x, s4 y) { x = bswap_32(y); }
-void SwappingEndian::set(s8& x, s8 y) { x = bswap_64(y); }
-
-SwappingEndian SwappingEndian::_swapping;
-
-Endian* Endian::get_handler(bool big_endian) {
- // If requesting little endian on a little endian machine or
- // big endian on a big endian machine use native handler
- if (big_endian == is_big_endian()) {
- return NativeEndian::get_native();
- } else {
- // Use swapping handler.
- return SwappingEndian::get_swapping();
- }
-}
-
-Endian* Endian::get_native_handler() {
- return NativeEndian::get_native();
-}
--- a/hotspot/src/share/vm/utilities/endian.hpp Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 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 SHARE_VM_UTILITIES_ENDIAN_HPP
-#define SHARE_VM_UTILITIES_ENDIAN_HPP
-
-#include "utilities/globalDefinitions.hpp"
-
-// Selectable endian handling. Endian handlers are used when accessing values
-// that are of unknown (until runtime) endian. The only requirement of the values
-// accessed are that they are aligned to proper size boundaries (no misalignment.)
-// To select an endian handler, one should call Endian::get_handler(big_endian);
-// Where big_endian is true if big endian is required and false otherwise. The
-// native endian handler can be fetched with Endian::get_native_handler();
-// To retrieve a value using the approprate endian, use one of the overloaded
-// calls to get. To set a value, then use one of the overloaded set calls.
-// Ex.
-// s4 value; // Imported value;
-// ...
-// Endian* endian = Endian::get_handler(true); // Use big endian
-// s4 corrected = endian->get(value);
-// endian->set(value, 1);
-//
-class Endian {
-public:
- virtual u2 get(u2 x) = 0;
- virtual u4 get(u4 x) = 0;
- virtual u8 get(u8 x) = 0;
- virtual s2 get(s2 x) = 0;
- virtual s4 get(s4 x) = 0;
- virtual s8 get(s8 x) = 0;
-
- virtual void set(u2& x, u2 y) = 0;
- virtual void set(u4& x, u4 y) = 0;
- virtual void set(u8& x, u8 y) = 0;
- virtual void set(s2& x, s2 y) = 0;
- virtual void set(s4& x, s4 y) = 0;
- virtual void set(s8& x, s8 y) = 0;
-
- // Quick little endian test.
- static bool is_little_endian() { u4 x = 1; return *(u1 *)&x != 0; }
-
- // Quick big endian test.
- static bool is_big_endian() { return !is_little_endian(); }
-
- // Select an appropriate endian handler.
- static Endian* get_handler(bool big_endian);
-
- // Return the native endian handler.
- static Endian* get_native_handler();
-};
-
-// Normal endian handling.
-class NativeEndian : public Endian {
-private:
- static NativeEndian _native;
-
-public:
- u2 get(u2 x);
- u4 get(u4 x);
- u8 get(u8 x);
- s2 get(s2 x);
- s4 get(s4 x);
- s8 get(s8 x);
-
- void set(u2& x, u2 y);
- void set(u4& x, u4 y);
- void set(u8& x, u8 y);
- void set(s2& x, s2 y);
- void set(s4& x, s4 y);
- void set(s8& x, s8 y);
-
- static Endian* get_native() { return &_native; }
-};
-
-// Swapping endian handling.
-class SwappingEndian : public Endian {
-private:
- static SwappingEndian _swapping;
-
-public:
- u2 get(u2 x);
- u4 get(u4 x);
- u8 get(u8 x);
- s2 get(s2 x);
- s4 get(s4 x);
- s8 get(s8 x);
-
- void set(u2& x, u2 y);
- void set(u4& x, u4 y);
- void set(u8& x, u8 y);
- void set(s2& x, s2 y);
- void set(s4& x, s4 y);
- void set(s8& x, s8 y);
-
- static Endian* get_swapping() { return &_swapping; }
-};
-#endif // SHARE_VM_UTILITIES_ENDIAN_HPP
--- a/hotspot/src/share/vm/utilities/stack.inline.hpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/utilities/stack.inline.hpp Mon Sep 14 07:03:04 2015 +0000
@@ -27,6 +27,17 @@
#include "utilities/stack.hpp"
+// Stack is used by the GC code and in some hot paths a lot of the Stack
+// code gets inlined. This is generally good, but when too much code has
+// been inlined, no further inlining is allowed by GCC. Therefore we need
+// to prevent parts of the slow path in Stack to be inlined to allow other
+// code to be.
+#if defined(TARGET_COMPILER_gcc)
+#define NOINLINE __attribute__((noinline))
+#else
+#define NOINLINE
+#endif
+
template <MEMFLAGS F> StackBase<F>::StackBase(size_t segment_size, size_t max_cache_size,
size_t max_size):
_seg_size(segment_size),
@@ -141,7 +152,7 @@
}
template <class E, MEMFLAGS F>
-void Stack<E, F>::push_segment()
+NOINLINE void Stack<E, F>::push_segment()
{
assert(this->_cur_seg_size == this->_seg_size, "current segment is not full");
E* next;
@@ -269,4 +280,6 @@
return _cur_seg + --_cur_seg_size;
}
+#undef NOINLINE
+
#endif // SHARE_VM_UTILITIES_STACK_INLINE_HPP
--- a/hotspot/src/share/vm/utilities/vmError.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -231,7 +231,7 @@
if (signame) {
jio_snprintf(buf, buflen,
- "%s (0x%x) at pc=" PTR_FORMAT ", pid=%d, tid=" INTPTR_FORMAT,
+ "%s (0x%x) at pc=" PTR_FORMAT ", pid=%d, tid=" UINTX_FORMAT,
signame, _id, _pc,
os::current_process_id(), os::current_thread_id());
} else if (_filename != NULL && _lineno > 0) {
@@ -239,7 +239,7 @@
char separator = os::file_separator()[0];
const char *p = strrchr(_filename, separator);
int n = jio_snprintf(buf, buflen,
- "Internal Error at %s:%d, pid=%d, tid=" INTPTR_FORMAT,
+ "Internal Error at %s:%d, pid=%d, tid=" UINTX_FORMAT,
p ? p + 1 : _filename, _lineno,
os::current_process_id(), os::current_thread_id());
if (n >= 0 && n < buflen && _message) {
@@ -253,7 +253,7 @@
}
} else {
jio_snprintf(buf, buflen,
- "Internal Error (0x%x), pid=%d, tid=" INTPTR_FORMAT,
+ "Internal Error (0x%x), pid=%d, tid=" UINTX_FORMAT,
_id, os::current_process_id(), os::current_thread_id());
}
@@ -486,7 +486,7 @@
// process id, thread id
st->print(", pid=%d", os::current_process_id());
- st->print(", tid=" INTPTR_FORMAT, os::current_thread_id());
+ st->print(", tid=" UINTX_FORMAT, os::current_thread_id());
st->cr();
STEP(80, "(printing error message)")
--- a/hotspot/test/compiler/arguments/CheckCICompilerCount.java Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/test/compiler/arguments/CheckCICompilerCount.java Mon Sep 14 07:03:04 2015 +0000
@@ -75,7 +75,7 @@
"intx CICompilerCount := 1 {product}"
},
{
- "CICompilerCount=0 must be at least 1",
+ "CICompilerCount (0) must be at least 1",
"Improperly specified VM option 'CICompilerCount=0'"
},
{
@@ -130,7 +130,7 @@
"intx CICompilerCount := 2 {product}"
},
{
- "CICompilerCount=1 must be at least 2",
+ "CICompilerCount (1) must be at least 2",
"Improperly specified VM option 'CICompilerCount=1'"
},
{
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestArrayCopyOverflowInBoundChecks.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8134468
+ * @summary test that checks whether an array load falls into the range of an arraycopy is incorrect on 32bits
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayCopyOverflowInBoundChecks
+ *
+ */
+public class TestArrayCopyOverflowInBoundChecks {
+
+ static byte[] src_array = { 'a', 'b', 'c', 'd', 'e' };
+
+ static byte test(int copy_len) {
+ byte[] dst_array = new byte[10];
+ System.arraycopy(src_array, 0, dst_array, 1, copy_len);
+ return dst_array[1];
+ }
+
+ static public void main(String[] args) {
+ for (int i = 0; i < 20000; i++) {
+ if (test(src_array.length - 1) != src_array[0]) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/escapeAnalysis/TestEABadMergeMem.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8134031
+ * @summary Bad rewiring of memory edges when we split unique types during EA
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand=dontinline,TestEABadMergeMem::m_notinlined TestEABadMergeMem
+ *
+ */
+
+public class TestEABadMergeMem {
+
+ static class Box {
+ int i;
+ }
+
+ static void m_notinlined() {
+ }
+
+ static float dummy1;
+ static float dummy2;
+
+ static int test(Box a, Box c, int i, int j, int k, boolean flag1, boolean flag2) {
+ Box b = new Box(); // non escaping
+ a.i = i;
+ b.i = j;
+ c.i = k;
+
+ m_notinlined();
+
+ boolean flag3 = false;
+ if (flag1) {
+ for (int ii = 0; ii < 100; ii++) {
+ if (flag2) {
+ dummy1 = (float)ii;
+ } else {
+ dummy2 = (float)ii;
+ }
+ }
+ flag3 = true;
+ }
+ // Memory Phi here with projection of not inlined call as one edge, MergeMem as other
+
+ if (flag3) { // will split through Phi during loopopts
+ int res = c.i + b.i;
+ m_notinlined(); // prevents split through phi during igvn
+ return res;
+ } else {
+ return 44 + 43;
+ }
+ }
+
+ static public void main(String[] args) {
+ for (int i = 0; i < 20000; i++) {
+ // m(2);
+ Box a = new Box();
+ Box c = new Box();
+ int res = test(a, c, 42, 43, 44, (i%2) == 0, (i%3) == 0);
+ if (res != 44 + 43) {
+ throw new RuntimeException("Bad result " + res);
+ }
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/adler32/TestAdler32.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8132081
+ * @summary C2 support for Adler32 on SPARC
+ *
+ * @run main/othervm/timeout=600 -Xbatch TestAdler32 -m
+ */
+
+import java.nio.ByteBuffer;
+import java.util.zip.Checksum;
+import java.util.zip.Adler32;
+
+public class TestAdler32 {
+ public static void main(String[] args) {
+ int offset = Integer.getInteger("offset", 0);
+ int msgSize = Integer.getInteger("msgSize", 512);
+ boolean multi = false;
+ int iters = 20000;
+ int warmupIters = 20000;
+
+ if (args.length > 0) {
+ if (args[0].equals("-m")) {
+ multi = true;
+ } else {
+ iters = Integer.valueOf(args[0]);
+ }
+ if (args.length > 1) {
+ warmupIters = Integer.valueOf(args[1]);
+ }
+ }
+
+ if (multi) {
+ test_multi(warmupIters);
+ return;
+ }
+
+ System.out.println(" offset = " + offset);
+ System.out.println("msgSize = " + msgSize + " bytes");
+ System.out.println(" iters = " + iters);
+
+ byte[] b = initializedBytes(msgSize, offset);
+
+ Adler32 adler0 = new Adler32();
+ Adler32 adler1 = new Adler32();
+ Adler32 adler2 = new Adler32();
+
+ adler0.update(b, offset, msgSize);
+
+ System.out.println("-------------------------------------------------------");
+
+ /* warm up */
+ for (int i = 0; i < warmupIters; i++) {
+ adler1.reset();
+ adler1.update(b, offset, msgSize);
+ }
+
+ /* measure performance */
+ long start = System.nanoTime();
+ for (int i = 0; i < iters; i++) {
+ adler1.reset();
+ adler1.update(b, offset, msgSize);
+ }
+ long end = System.nanoTime();
+ double total = (double)(end - start)/1e9; // in seconds
+ double thruput = (double)msgSize*iters/1e6/total; // in MB/s
+ System.out.println("Adler32.update(byte[]) runtime = " + total + " seconds");
+ System.out.println("Adler32.update(byte[]) throughput = " + thruput + " MB/s");
+
+ /* check correctness */
+ for (int i = 0; i < iters; i++) {
+ adler1.reset();
+ adler1.update(b, offset, msgSize);
+ if (!check(adler0, adler1)) break;
+ }
+ report("Adlers", adler0, adler1);
+
+ System.out.println("-------------------------------------------------------");
+
+ ByteBuffer buf = ByteBuffer.allocateDirect(msgSize);
+ buf.put(b, offset, msgSize);
+ buf.flip();
+
+ /* warm up */
+ for (int i = 0; i < warmupIters; i++) {
+ adler2.reset();
+ adler2.update(buf);
+ buf.rewind();
+ }
+
+ /* measure performance */
+ start = System.nanoTime();
+ for (int i = 0; i < iters; i++) {
+ adler2.reset();
+ adler2.update(buf);
+ buf.rewind();
+ }
+ end = System.nanoTime();
+ total = (double)(end - start)/1e9; // in seconds
+ thruput = (double)msgSize*iters/1e6/total; // in MB/s
+ System.out.println("Adler32.update(ByteBuffer) runtime = " + total + " seconds");
+ System.out.println("Adler32.update(ByteBuffer) throughput = " + thruput + " MB/s");
+
+ /* check correctness */
+ for (int i = 0; i < iters; i++) {
+ adler2.reset();
+ adler2.update(buf);
+ buf.rewind();
+ if (!check(adler0, adler2)) break;
+ }
+ report("Adlers", adler0, adler1);
+
+ System.out.println("-------------------------------------------------------");
+ }
+
+ private static void report(String s, Checksum adler0, Checksum adler1) {
+ System.out.printf("%s: adler0 = %08x, adler1 = %08x\n",
+ s, adler0.getValue(), adler1.getValue());
+ }
+
+ private static boolean check(Checksum adler0, Checksum adler1) {
+ if (adler0.getValue() != adler1.getValue()) {
+ System.err.printf("ERROR: adler0 = %08x, adler1 = %08x\n",
+ adler0.getValue(), adler1.getValue());
+ return false;
+ }
+ return true;
+ }
+
+ private static byte[] initializedBytes(int M, int offset) {
+ byte[] bytes = new byte[M + offset];
+ for (int i = 0; i < offset; i++) {
+ bytes[i] = (byte) i;
+ }
+ for (int i = offset; i < bytes.length; i++) {
+ bytes[i] = (byte) (i - offset);
+ }
+ return bytes;
+ }
+
+ private static void test_multi(int iters) {
+ int len1 = 8; // the 8B/iteration loop
+ int len2 = 32; // the 32B/iteration loop
+ int len3 = 4096; // the 4KB/iteration loop
+
+ byte[] b = initializedBytes(len3*16, 0);
+ int[] offsets = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512 };
+ int[] sizes = { 0, 1, 2, 3, 4, 5, 6, 7,
+ len1, len1+1, len1+2, len1+3, len1+4, len1+5, len1+6, len1+7,
+ len1*2, len1*2+1, len1*2+3, len1*2+5, len1*2+7,
+ len2, len2+1, len2+3, len2+5, len2+7,
+ len2*2, len2*4, len2*8, len2*16, len2*32, len2*64,
+ len3, len3+1, len3+3, len3+5, len3+7,
+ len3*2, len3*4, len3*8,
+ len1+len2, len1+len2+1, len1+len2+3, len1+len2+5, len1+len2+7,
+ len1+len3, len1+len3+1, len1+len3+3, len1+len3+5, len1+len3+7,
+ len2+len3, len2+len3+1, len2+len3+3, len2+len3+5, len2+len3+7,
+ len1+len2+len3, len1+len2+len3+1, len1+len2+len3+3,
+ len1+len2+len3+5, len1+len2+len3+7,
+ (len1+len2+len3)*2, (len1+len2+len3)*2+1, (len1+len2+len3)*2+3,
+ (len1+len2+len3)*2+5, (len1+len2+len3)*2+7,
+ (len1+len2+len3)*3, (len1+len2+len3)*3-1, (len1+len2+len3)*3-3,
+ (len1+len2+len3)*3-5, (len1+len2+len3)*3-7 };
+ Adler32[] adler0 = new Adler32[offsets.length*sizes.length];
+ Adler32[] adler1 = new Adler32[offsets.length*sizes.length];
+ int i, j, k;
+
+ System.out.printf("testing %d cases ...\n", offsets.length*sizes.length);
+
+ /* set the result from interpreter as reference */
+ for (i = 0; i < offsets.length; i++) {
+ for (j = 0; j < sizes.length; j++) {
+ adler0[i*sizes.length + j] = new Adler32();
+ adler1[i*sizes.length + j] = new Adler32();
+ adler0[i*sizes.length + j].update(b, offsets[i], sizes[j]);
+ }
+ }
+
+ /* warm up the JIT compiler and get result */
+ for (k = 0; k < iters; k++) {
+ for (i = 0; i < offsets.length; i++) {
+ for (j = 0; j < sizes.length; j++) {
+ adler1[i*sizes.length + j].reset();
+ adler1[i*sizes.length + j].update(b, offsets[i], sizes[j]);
+ }
+ }
+ }
+
+ /* check correctness */
+ for (i = 0; i < offsets.length; i++) {
+ for (j = 0; j < sizes.length; j++) {
+ if (!check(adler0[i*sizes.length + j], adler1[i*sizes.length + j])) {
+ System.out.printf("offsets[%d] = %d", i, offsets[i]);
+ System.out.printf("\tsizes[%d] = %d\n", j, sizes[j]);
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/loopopts/superword/SumRedSqrt_Double.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+* @test
+* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : double sqrt test
+*
+* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
+* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
+*
+* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=4 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
+* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=4 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
+*
+* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=8 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
+* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=8 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
+*
+* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=16 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
+* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=16 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
+*/
+
+public class SumRedSqrt_Double
+{
+ public static void main(String[] args) throws Exception {
+ double[] a = new double[256*1024];
+ double[] b = new double[256*1024];
+ double[] c = new double[256*1024];
+ double[] d = new double[256*1024];
+ sumReductionInit(a,b,c);
+ double total = 0;
+ double valid = 2.06157643776E14;
+ for(int j = 0; j < 2000; j++) {
+ total = sumReductionImplement(a,b,c,d,total);
+ }
+ if(total == valid) {
+ System.out.println("Success");
+ } else {
+ System.out.println("Invalid sum of elements variable in total: " + total);
+ System.out.println("Expected value = " + valid);
+ throw new Exception("Failed");
+ }
+ }
+
+ public static void sumReductionInit(
+ double[] a,
+ double[] b,
+ double[] c)
+ {
+ for(int j = 0; j < 1; j++)
+ {
+ for(int i = 0; i < a.length; i++)
+ {
+ a[i] = i * 1 + j;
+ b[i] = i * 1 - j;
+ c[i] = i + j;
+ }
+ }
+ }
+
+ public static double sumReductionImplement(
+ double[] a,
+ double[] b,
+ double[] c,
+ double[] d,
+ double total)
+ {
+ for(int i = 0; i < a.length; i++)
+ {
+ d[i]= Math.sqrt(a[i] * b[i]) + Math.sqrt(a[i] * c[i]) + Math.sqrt(b[i] * c[i]);
+ total += d[i];
+ }
+ return total;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/GCTypes.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,115 @@
+/*
+* Copyright (c) 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.
+*/
+
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Helper class with enum representation of GC types.
+ */
+public final class GCTypes {
+
+ private static <T extends GCType> T getCurrentGCType(Class<T> type) {
+ return ManagementFactory.getGarbageCollectorMXBeans().stream()
+ .map(bean -> getGCTypeByName(type, bean.getName()))
+ .filter(Objects::nonNull)
+ .findFirst()
+ .orElse(null);
+ }
+
+ private static <T extends GCType> T getGCTypeByName(Class<T> type, String name) {
+ return Arrays.stream(type.getEnumConstants())
+ .filter(e -> e.getGCName().equals(name))
+ .findFirst()
+ .orElse(null);
+ }
+
+ private static <T extends GCType> GarbageCollectorMXBean getGCBeanByType(Class<T> type) {
+ return ManagementFactory.getGarbageCollectorMXBeans().stream()
+ .filter(bean -> Arrays.stream(type.getEnumConstants())
+ .filter(enumName -> enumName.getGCName().equals(bean.getName()))
+ .findFirst()
+ .isPresent()
+ )
+ .findFirst()
+ .orElse(null);
+ }
+
+ /**
+ * Helper interface used by GCTypes static methods
+ * to get gcTypeName field of *GCType classes.
+ */
+ private interface GCType {
+
+ String getGCName();
+ }
+
+ public static enum YoungGCType implements GCType {
+ DefNew("Copy"),
+ ParNew("ParNew"),
+ PSNew("PS Scavenge"),
+ G1("G1 Young Generation");
+
+ @Override
+ public String getGCName() {
+ return gcTypeName;
+ }
+ private final String gcTypeName;
+
+ private YoungGCType(String name) {
+ gcTypeName = name;
+ }
+
+ public static YoungGCType getYoungGCType() {
+ return GCTypes.getCurrentGCType(YoungGCType.class);
+ }
+
+ public static GarbageCollectorMXBean getYoungGCBean() {
+ return GCTypes.getGCBeanByType(YoungGCType.class);
+ }
+ }
+
+ public static enum OldGCType implements GCType {
+ Serial("MarkSweepCompact"),
+ CMS("ConcurrentMarkSweep"),
+ PSOld("PS MarkSweep"),
+ G1("G1 Old Generation");
+
+ private final String gcTypeName;
+
+ private OldGCType(String name) {
+ gcTypeName = name;
+ }
+
+ public static OldGCType getOldGCType() {
+ return GCTypes.getCurrentGCType(OldGCType.class);
+ }
+
+ @Override
+ public String getGCName() {
+ return gcTypeName;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,299 @@
+/*
+* Copyright (c) 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.
+*/
+
+/*
+ * @test TestMaxMinHeapFreeRatioFlags
+ * @key gc
+ * @summary Verify that heap size changes according to max and min heap free ratios.
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.management
+ * @build TestMaxMinHeapFreeRatioFlags
+ * @run driver/timeout=240 TestMaxMinHeapFreeRatioFlags
+ */
+
+import java.util.LinkedList;
+import java.util.Arrays;
+import java.util.Collections;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+import jdk.test.lib.HeapRegionUsageTool;
+import sun.misc.Unsafe;
+
+public class TestMaxMinHeapFreeRatioFlags {
+
+ public static final long M = 1024 * 1024;
+ public static final long MAX_HEAP_SIZE = 200 * M;
+ public static final long HEAP_SIZE = 10 * M;
+ public static final long MAX_NEW_SIZE = 20 * M;
+ public static final long NEW_SIZE = 5 * M;
+
+ public static void main(String args[]) throws Exception {
+ LinkedList<String> options = new LinkedList<>(
+ Arrays.asList(Utils.getFilteredTestJavaOpts("-XX:[^ ]*HeapFreeRatio","-XX:\\+ExplicitGCInvokesConcurrent"))
+ );
+
+ negativeTest(20, false, 10, true, options);
+ negativeTest(100, true, 0, false, options);
+ negativeTest(101, false, 50, false, options);
+ negativeTest(49, true, 102, true, options);
+ negativeTest(-1, false, 50, false, options);
+ negativeTest(50, true, -1, true, options);
+
+ positiveTest(10, false, 90, false, options);
+ positiveTest(10, true, 80, false, options);
+ positiveTest(20, false, 70, true, options);
+ positiveTest(25, true, 65, true, options);
+ positiveTest(40, false, 50, false, options);
+ }
+
+ /**
+ * Verify that heap size will be changed to conform
+ * min and max heap free ratios.
+ *
+ * @param minRatio value of MinHeapFreeRatio option
+ * @param useXminf used Xminf option instead of MinHeapFreeRatio
+ * @param maxRatio value of MaxHeapFreeRatio option
+ * @param useXmaxf used Xmaxf option instead of MaxHeapFreeRatio
+ * @param options additional options for JVM
+ */
+ public static void positiveTest(int minRatio, boolean useXminf,
+ int maxRatio, boolean useXmaxf,
+ LinkedList<String> options) throws Exception {
+
+ LinkedList<String> vmOptions = new LinkedList<>(options);
+ Collections.addAll(vmOptions,
+ (useXminf ? "-Xminf" + minRatio / 100.0 : "-XX:MinHeapFreeRatio=" + minRatio),
+ (useXmaxf ? "-Xmaxf" + maxRatio / 100.0 : "-XX:MaxHeapFreeRatio=" + maxRatio),
+ "-Xmx" + MAX_HEAP_SIZE,
+ "-Xms" + HEAP_SIZE,
+ "-XX:NewSize=" + NEW_SIZE,
+ "-XX:MaxNewSize=" + MAX_NEW_SIZE,
+ RatioVerifier.class.getName(),
+ Integer.toString(minRatio),
+ Integer.toString(maxRatio)
+ );
+
+ ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+ OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+ analyzer.shouldHaveExitValue(0);
+ }
+
+ /**
+ * Verify that VM will fail to start with specified ratios.
+ *
+ * @param minRatio value of MinHeapFreeRatio option
+ * @param useXminf used Xminf option instead of MinHeapFreeRatio
+ * @param maxRatio value of MaxHeapFreeRatio option
+ * @param useXmaxf used Xmaxf option instead of MaxHeapFreeRatio
+ * @param options additional options for JVM
+ */
+ public static void negativeTest(int minRatio, boolean useXminf,
+ int maxRatio, boolean useXmaxf,
+ LinkedList<String> options) throws Exception {
+
+ LinkedList<String> vmOptions = new LinkedList<>(options);
+ Collections.addAll(vmOptions,
+ (useXminf ? "-Xminf" + minRatio / 100.0 : "-XX:MinHeapFreeRatio=" + minRatio),
+ (useXmaxf ? "-Xmaxf" + maxRatio / 100.0 : "-XX:MaxHeapFreeRatio=" + maxRatio),
+ "-version"
+ );
+ ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+ OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+ analyzer.shouldHaveExitValue(1);
+ analyzer.shouldContain("Error: Could not create the Java Virtual Machine.");
+ }
+
+ /**
+ * RatioVerifier will be executed in the tested VM.
+ * It will check that real heap usage after collection lies between MinHeapFreeRatio and MaxHeapFreeRatio.
+ */
+ public static class RatioVerifier {
+
+ private static final Unsafe unsafe = Utils.getUnsafe();
+
+ // Size of byte array that will be allocated
+ public static final int CHUNK_SIZE = 1024;
+ // Length of byte array, that will be added to "garbage" list.
+ public static final int ARRAY_LENGTH = CHUNK_SIZE - Unsafe.ARRAY_BYTE_BASE_OFFSET;
+ // Amount of tries to force heap shrinking/expansion using GC
+ public static final int GC_TRIES = 10;
+
+ // Value that will be added/substracted from expected min/max heap free ratio
+ // during memory allocation to make sure that specified limit will be exceeded.
+ public static final double OVERLOAD = 0.05;
+ // Acceptable heap free ratio limit exceedance: verification will fail if
+ // actual ratio is lower than expected min heap free ratio - VARIANCE or
+ // higher than expected max heap free ratio + VARIANCE.
+ public static final double VARIANCE = 0.025;
+
+ public static LinkedList<Object> garbage = new LinkedList<>();
+
+ public static void main(String args[]) throws Exception {
+ if (args.length != 2) {
+ throw new IllegalArgumentException("Expected 2 args: <minRatio> <maxRatio>");
+ }
+ if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.PSOld) {
+ System.out.println("Test is not applicable to parallel GC");
+ return;
+ }
+
+ double minRatio = Integer.valueOf(args[0]) / 100.0;
+ double maxRatio = Integer.valueOf(args[1]) / 100.0;
+
+ long maxHeapSize = getMax();
+
+ // commit 0.5 of total heap size to have enough space
+ // to both shink and expand
+ while (getCommitted() < maxHeapSize / 2) {
+ garbage.add(new byte[ARRAY_LENGTH]);
+ }
+
+ forceGC();
+ // Verify that current heap free ratio lies between specified limits
+ verifyRatio(minRatio, maxRatio);
+
+ // Estimate how much memory we have to allocate to force expansion
+ long memoryToFill = (long) (getCommitted() * (1 - minRatio + OVERLOAD))
+ - getUsed();
+
+ long previouslyCommitted = getCommitted();
+
+ while (memoryToFill > 0) {
+ garbage.add(new byte[CHUNK_SIZE]);
+ memoryToFill -= CHUNK_SIZE;
+ }
+
+ forceGC();
+ // Verify that after memory allocation heap free ratio is still conforming specified limits
+ verifyRatio(minRatio, maxRatio);
+ // Verify that heap was actually expanded
+ if (previouslyCommitted >= getCommitted()) {
+ throw new RuntimeException("Heap was not expanded.");
+ }
+
+ // Estimate how much memory we have to free to force shrinking
+ long memoryToFree = getUsed()
+ - (long) (getCommitted() * (1 - maxRatio - OVERLOAD));
+
+ previouslyCommitted = getCommitted();
+
+ while (memoryToFree > 0 && garbage.size() > 0) {
+ garbage.remove(garbage.size() - 1);
+ memoryToFree -= CHUNK_SIZE;
+ }
+
+ forceGC();
+ // Verify that heap free ratio is still conforming specified limits
+ verifyRatio(minRatio, maxRatio);
+ // Verify that heap was actually shrinked
+ if (previouslyCommitted <= getCommitted()) {
+ throw new RuntimeException("Heap was not shrinked.");
+ }
+
+ }
+
+ public static void forceGC() {
+ for (int i = 0; i < GC_TRIES; i++) {
+ System.gc();
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+
+ /**
+ * Verify that heap free ratio is conforming specified limits.
+ * Actual heap free ratio may be very close to one of specified limits,
+ * but exceed for more then VARIANCE.
+ * Verification will also pass if actual ratio is not conforming limits,
+ * but it is not possible to shrink/expand heap.
+ */
+ public static void verifyRatio(double minRatio, double maxRatio) {
+ double ratio = getHeapFreeRatio();
+ System.out.println(minRatio + " " + ratio + " " + maxRatio);
+ if (minRatio - ratio > VARIANCE
+ && getCommitted() < getMax()) {
+ throw new RuntimeException("Current heap free ratio is lower than "
+ + "MinHeapFreeRatio (" + ratio + " vs " + minRatio + ").");
+ }
+ if (ratio - maxRatio > VARIANCE
+ && getUsed() > getInit()) {
+ throw new RuntimeException("Current heap free ratio is higher than "
+ + "MaxHeapFreeRatio (" + ratio + " vs " + maxRatio + ").");
+ }
+ }
+
+ /*
+ * Obtain information about heap size.
+ *
+ * For G1 information summed up for all type of regions,
+ * because tested options affect overall heap sizing.
+ *
+ * For all other GCs return information only for old gen.
+ */
+ public static long getMax() {
+ return HeapRegionUsageTool.getOldUsage().getMax();
+ }
+
+ public static long getInit() {
+ if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.G1) {
+ return HeapRegionUsageTool.getEdenUsage().getInit()
+ + HeapRegionUsageTool.getSurvivorUsage().getInit()
+ + HeapRegionUsageTool.getOldUsage().getInit();
+ } else {
+ return HeapRegionUsageTool.getOldUsage().getInit();
+ }
+ }
+
+ public static long getUsed() {
+ if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.G1) {
+ return HeapRegionUsageTool.getEdenUsage().getUsed()
+ + HeapRegionUsageTool.getSurvivorUsage().getUsed()
+ + HeapRegionUsageTool.getOldUsage().getUsed();
+ } else {
+ return HeapRegionUsageTool.getOldUsage().getUsed();
+ }
+ }
+
+ public static long getCommitted() {
+ if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.G1) {
+ return HeapRegionUsageTool.getEdenUsage().getCommitted()
+ + HeapRegionUsageTool.getSurvivorUsage().getCommitted()
+ + HeapRegionUsageTool.getOldUsage().getCommitted();
+ } else {
+ return HeapRegionUsageTool.getOldUsage().getCommitted();
+ }
+ }
+
+ public static long getFree() {
+ return getCommitted() - getUsed();
+ }
+
+ public static double getHeapFreeRatio() {
+ return getFree() / (double) getCommitted();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,206 @@
+/*
+* Copyright (c) 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.
+*/
+
+/*
+ * @test TestMinAndInitialSurvivorRatioFlags
+ * @key gc
+ * @summary Verify that MinSurvivorRatio and InitialSurvivorRatio flags work
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.management
+ * @build TestMinAndInitialSurvivorRatioFlags
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver TestMinAndInitialSurvivorRatioFlags
+ */
+
+import jdk.test.lib.AllocationHelper;
+import java.lang.management.MemoryUsage;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import jdk.test.lib.HeapRegionUsageTool;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+/* Test verifies that VM can start with any GC when MinSurvivorRatio and
+ * InitialSurvivorRatio flags passed and for Parallel GC it verifies that
+ * after start up survivor ratio equal to InitialSurvivorRatio value and
+ * that actual survivor ratio will never be less than MinSurvivorRatio.
+ */
+public class TestMinAndInitialSurvivorRatioFlags {
+
+ public static final long M = 1024 * 1024;
+ public static final long HEAP_SIZE = 200 * M;
+ public static final long NEW_SIZE = 100 * M;
+
+ public static void main(String args[]) throws Exception {
+ LinkedList<String> options = new LinkedList<>(
+ Arrays.asList(Utils.getFilteredTestJavaOpts("-XX:[^ ]*SurvivorRatio=[^ ]+"))
+ );
+
+ testSurvivorRatio(5, -1, -1, options, true);
+ testSurvivorRatio(10, -1, -1, options, true);
+ testSurvivorRatio(-1, 5, 3, options, true);
+ testSurvivorRatio(-1, 15, 3, options, true);
+ testSurvivorRatio(-1, 15, 3, options, false);
+ testSurvivorRatio(-1, 10, 10, options, true);
+ testSurvivorRatio(-1, 3, 15, options, true);
+ testSurvivorRatio(-1, 3, 15, options, false);
+ }
+
+ /**
+ * Test that MinSurvivorRatio and InitialSurvivorRatio flags work.
+ *
+ * @param survivorRatio value for -XX:SurvivorRatio option, omitted if negative
+ * @param initRatio value for -XX:InitialSurvivorRatio option, omitted if negative
+ * @param minRatio value for -XX:MinSurvivorRatio option, omitted if negative
+ * @param options additional options for VM
+ * @param useAdaptiveSizePolicy turn on or off UseAdaptiveSizePolicy option
+ */
+ public static void testSurvivorRatio(int survivorRatio,
+ int initRatio,
+ int minRatio,
+ LinkedList<String> options,
+ boolean useAdaptiveSizePolicy) throws Exception {
+
+ LinkedList<String> vmOptions = new LinkedList<>(options);
+ Collections.addAll(vmOptions,
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-XX:MaxNewSize=" + NEW_SIZE, "-XX:NewSize=" + NEW_SIZE,
+ "-Xmx" + HEAP_SIZE, "-Xms" + HEAP_SIZE,
+ (survivorRatio >= 0 ? "-XX:SurvivorRatio=" + survivorRatio : ""),
+ (initRatio >= 0 ? "-XX:InitialSurvivorRatio=" + initRatio : ""),
+ (minRatio >= 0 ? "-XX:MinSurvivorRatio=" + minRatio : ""),
+ (useAdaptiveSizePolicy ? "-XX:+UseAdaptiveSizePolicy" : "-XX:-UseAdaptiveSizePolicy"),
+ SurvivorRatioVerifier.class.getName(),
+ Integer.toString(survivorRatio),
+ Integer.toString(initRatio),
+ Integer.toString(minRatio),
+ Boolean.toString(useAdaptiveSizePolicy)
+ );
+ vmOptions.removeIf((String p) -> p.isEmpty());
+ ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+ OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+ analyzer.shouldHaveExitValue(0);
+ }
+
+ /**
+ * Class that verifies survivor ratio.
+ * Will be executed in tested VM. Checks initial size of eden and survivor paces with alignment.
+ */
+ public static class SurvivorRatioVerifier {
+
+ public static WhiteBox wb = WhiteBox.getWhiteBox();
+
+ public static final int MAX_ITERATIONS = 10;
+ public static final int ARRAY_LENGTH = 10000;
+ public static final int CHUNK_SIZE = 10000;
+
+ public static byte garbage[][] = new byte[ARRAY_LENGTH][];
+
+ public static void main(String args[]) throws Exception {
+ if (args.length != 4) {
+ throw new IllegalArgumentException("Expected 4 args: <survivorRatio> <initRatio> <minRatio> <useAdaptiveSizePolicy>");
+ }
+ final int survivorRatio = Integer.valueOf(args[0]);
+ final int initRatio = Integer.valueOf(args[1]);
+ final int minRatio = Integer.valueOf(args[2]);
+ final boolean useAdaptiveSizePolicy = Boolean.valueOf(args[3]);
+
+ // we stop testing only here to ensure that JVM will accept
+ // both MinSurvivorRatio and InitialSurvivorRatio regardles to GC
+ if (GCTypes.YoungGCType.getYoungGCType() != GCTypes.YoungGCType.PSNew) {
+ System.out.println("Test is only applicable to Parallel GC");
+ return;
+ }
+
+ // verify initial survivor ratio
+ verifySurvivorRatio(survivorRatio, initRatio, minRatio, useAdaptiveSizePolicy, true);
+
+ // force GC
+ AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE,
+ () -> (verifySurvivorRatio(survivorRatio, initRatio, minRatio, useAdaptiveSizePolicy, false)));
+ allocator.allocateMemoryAndVerify();
+ }
+
+ /**
+ * Verify actual survivor ratio.
+ *
+ * @param survivorRatio value of SurvivorRatio option, omitted if negative
+ * @param initRatio value of InitialSurvivorRatio option, omitted if negative
+ * @param minRatio value of MinSurvivorRatio option, omitted if negative
+ * @param useAdaptiveSizePolicy value of UseAdaptiveSizePolicy option
+ * @param verifyInitialRatio true if we are going to verify initial ratio
+ */
+ public static Void verifySurvivorRatio(int survivorRatio,
+ int initRatio,
+ int minRatio,
+ boolean useAdaptiveSizePolicy,
+ boolean verifyInitialRatio) {
+
+ MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage();
+ MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();
+
+ long alignedNewSize = edenUsage.getMax() + 2 * survivorUsage.getMax();
+ long generationAlignment = wb.psHeapGenerationAlignment();
+
+ if (survivorRatio >= 0) {
+ // -XX:SurvivorRatio was passed to JVM, actual ratio should be SurvivorRatio + 2
+ long expectedSize = HeapRegionUsageTool.alignDown(alignedNewSize / (survivorRatio + 2),
+ generationAlignment);
+
+ if (survivorUsage.getCommitted() != expectedSize) {
+ throw new RuntimeException("Expected survivor size is: " + expectedSize
+ + ", but observed size is: " + survivorUsage.getCommitted());
+ }
+ } else if (verifyInitialRatio || !useAdaptiveSizePolicy) {
+ // In case of initial ratio verification or disabled adaptive size policy
+ // ratio should be equal to InitialSurvivorRatio value
+ long expectedSize = HeapRegionUsageTool.alignDown(alignedNewSize / initRatio,
+ generationAlignment);
+ if (survivorUsage.getCommitted() != expectedSize) {
+ throw new RuntimeException("Expected survivor size is: " + expectedSize
+ + ", but observed size is: " + survivorUsage.getCommitted());
+ }
+ } else {
+ // In any other case actual survivor ratio should not be lower than MinSurvivorRatio
+ // or is should be equal to InitialSurvivorRatio
+ long expectedMinSize = HeapRegionUsageTool.alignDown(alignedNewSize / minRatio,
+ generationAlignment);
+ long expectedInitSize = HeapRegionUsageTool.alignDown(alignedNewSize / initRatio,
+ generationAlignment);
+ if (survivorUsage.getCommitted() != expectedInitSize
+ && survivorUsage.getCommitted() < expectedMinSize) {
+ throw new RuntimeException("Expected survivor size should be " + expectedMinSize
+ + " or should be greater then " + expectedMinSize
+ + ", but observer survivor size is " + survivorUsage.getCommitted());
+ }
+ }
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestNewRatioFlag.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 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.
+*/
+
+/*
+ * @test TestNewRatioFlag
+ * @key gc
+ * @bug 8025166
+ * @summary Verify that heap devided among generations according to NewRatio
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.management
+ * @build TestNewRatioFlag
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver TestNewRatioFlag
+ */
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import jdk.test.lib.HeapRegionUsageTool;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+public class TestNewRatioFlag {
+
+ public static final long M = 1024 * 1024;
+ public static final long HEAP_SIZE = 100 * M;
+
+ public static void main(String args[]) throws Exception {
+ LinkedList<String> options = new LinkedList<>(
+ Arrays.asList(Utils.getFilteredTestJavaOpts("(-XX:[^ ]*NewSize=[^ ]+)|(-Xm[ns][^ ]+)"))
+ );
+
+ testNewRatio(4, options);
+ testNewRatio(6, options);
+ testNewRatio(10, options);
+ testNewRatio(15, options);
+ testNewRatio(20, options);
+ }
+
+ /**
+ * Verify that actual size of young gen conforms specified NewRatio
+ *
+ * @param ratio value of NewRatio option
+ * @param options additional options for VM
+ */
+ public static void testNewRatio(int ratio, LinkedList<String> options) throws Exception {
+ LinkedList<String> vmOptions = new LinkedList<>(options);
+ Collections.addAll(vmOptions,
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-XX:GCLockerEdenExpansionPercent=0",
+ "-Xmx" + HEAP_SIZE,
+ "-Xms" + HEAP_SIZE,
+ "-XX:NewRatio=" + ratio,
+ "-XX:-UseLargePages",
+ NewRatioVerifier.class.getName(),
+ Integer.toString(ratio)
+ );
+
+ ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+ OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+ analyzer.shouldHaveExitValue(0);
+ System.out.println(analyzer.getOutput());
+ }
+
+ public static class NewRatioVerifier {
+
+ static WhiteBox wb = WhiteBox.getWhiteBox();
+
+ public static void main(String args[]) {
+ if (args.length != 1) {
+ throw new IllegalArgumentException("Expected 1 arg: <expectedRatio>");
+ }
+ int expectedRatio = Integer.valueOf(args[0]);
+ switch (GCTypes.YoungGCType.getYoungGCType()) {
+ case DefNew:
+ case ParNew:
+ verifyDefNewNewRatio(expectedRatio);
+ break;
+ case PSNew:
+ verifyPSNewRatio(expectedRatio);
+ break;
+ case G1:
+ verifyG1NewRatio(expectedRatio);
+ break;
+ default:
+ throw new RuntimeException("Unexpected young GC type");
+ }
+ }
+
+ /**
+ * Verify NewSize for DefNew and ParNew collectors.
+ *
+ * Compare expected NewSize calculated according to sizing policies used by DefNew
+ * with NewSize value reported by MemoryPoolMXBeans.
+ */
+ public static void verifyDefNewNewRatio(int expectedRatio) {
+ long initEden = HeapRegionUsageTool.getEdenUsage().getInit();
+ long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit();
+ long initOld = HeapRegionUsageTool.getOldUsage().getInit();
+
+ long newSize = initEden + 2 * initSurv;
+
+ long expectedNewSize = HeapRegionUsageTool.alignDown(initOld / expectedRatio,
+ wb.getHeapSpaceAlignment());
+
+ if (expectedNewSize != newSize) {
+ throw new RuntimeException("Expected young gen size is: " + expectedNewSize
+ + ", but observed new size is: " + newSize);
+ }
+ }
+
+ /**
+ * Verify NewSize for PS collector.
+ * Expected NewSize calculated according to alignment policies used by PS
+ * and then compared with actual NewSize obtained from MemoryPoolMXBeans.
+ */
+ public static void verifyPSNewRatio(int expectedRatio) {
+ long initEden = HeapRegionUsageTool.getEdenUsage().getInit();
+ long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit();
+ long initOld = HeapRegionUsageTool.getOldUsage().getInit();
+
+ long newSize = initEden + 2 * initSurv;
+
+ long alignedDownNewSize = HeapRegionUsageTool.alignDown(initOld / expectedRatio,
+ wb.getHeapSpaceAlignment());
+ long expectedNewSize = HeapRegionUsageTool.alignUp(alignedDownNewSize,
+ wb.psVirtualSpaceAlignment());
+
+ if (expectedNewSize != newSize) {
+ throw new RuntimeException("Expected young gen size is: " + expectedNewSize
+ + ", but observed new size is: " + newSize);
+ }
+ }
+
+ /**
+ * Verify NewSize for G1 GC.
+ * Amount of young regions calculated according to sizing policies used by G1
+ * and then compared with actual number of young regions derived from
+ * values reported by MemoryPoolMXBeans and region size.
+ */
+ public static void verifyG1NewRatio(int expectedRatio) {
+ long initEden = HeapRegionUsageTool.getEdenUsage().getInit();
+ long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit();
+ long maxOld = HeapRegionUsageTool.getOldUsage().getMax();
+
+ int regionSize = wb.g1RegionSize();
+ int youngListLength = (int) ((initEden + initSurv) / regionSize);
+ int maxRegions = (int) (maxOld / regionSize);
+ int expectedYoungListLength = (int) (maxRegions / (double) (expectedRatio + 1));
+
+ if (youngListLength != expectedYoungListLength) {
+ throw new RuntimeException("Expected G1 young list length is: " + expectedYoungListLength
+ + ", but observed young list length is: " + youngListLength);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestNewSizeFlags.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestNewSizeFlags
+ * @key gc
+ * @bug 8025166
+ * @summary Verify that young gen size conforms values specified by NewSize, MaxNewSize and Xmn options
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.management
+ * @build TestNewSizeFlags
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver/timeout=240 TestNewSizeFlags
+ */
+
+import jdk.test.lib.AllocationHelper;
+import java.io.IOException;
+import java.lang.management.MemoryUsage;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import jdk.test.lib.HeapRegionUsageTool;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+public class TestNewSizeFlags {
+
+ public static final long M = 1024 * 1024;
+
+ public static void main(String args[]) throws Exception {
+ LinkedList<String> options = new LinkedList<>(
+ Arrays.asList(Utils.getFilteredTestJavaOpts("(-Xm[nsx][^ ]+)|"
+ + "(-XX:(Max)?((New)|"
+ + "(Heap))((Size)|"
+ + "(Ratio))=[^ ]+)"))
+ );
+
+ // Test NewSize and MaxNewSize
+ testNewSizeFlags(20 * M, 10 * M, 30 * M, 40 * M, options, false);
+ testNewSizeFlags(10 * M, 20 * M, 30 * M, 40 * M, options, false);
+ testNewSizeFlags(-1, 20 * M, 30 * M, 40 * M, options, false);
+ testNewSizeFlags(10 * M, -1, 30 * M, 40 * M, options, false);
+ testNewSizeFlags(20 * M, 20 * M, 30 * M, 40 * M, options, false);
+ testNewSizeFlags(20 * M, 30 * M, 40 * M, 50 * M, options, false);
+ testNewSizeFlags(30 * M, 100 * M, 150 * M, 200 * M, options, false);
+ testNewSizeFlags(0, -1, 30 * M, 40 * M, options, false);
+
+ // Test -Xmn
+ testXmnFlags(0, 30 * M, 40 * M, options, true);
+ testXmnFlags(20 * M, 30 * M, 40 * M, options, false);
+ testXmnFlags(50 * M, 70 * M, 100 * M, options, false);
+ }
+
+ /**
+ * Verify that NewSize and MaxNewSize flags affect young gen size.
+ *
+ * @param newSize value of NewSize option, omitted if negative
+ * @param maxNewSize value of MaxNewSize option, omitted if negative
+ * @param heapSize value of HeapSize option
+ * @param maxHeapSize value of MaxHeapSize option
+ * @param options additional options for JVM
+ * @param failureExpected true if JVM should fail with passed heap size options
+ */
+ public static void testNewSizeFlags(long newSize, long maxNewSize,
+ long heapSize, long maxHeapSize,
+ LinkedList<String> options,
+ boolean failureExpected) throws Exception {
+ testVMOptions(newSize, maxNewSize,
+ heapSize, maxHeapSize,
+ newSize, (maxNewSize >= 0 ? Math.max(maxNewSize, newSize) : maxNewSize),
+ options, failureExpected);
+ }
+
+ /**
+ * Verify that -Xmn flag affect young gen size.
+ *
+ * @param mnValue value of -Xmn option
+ * @param heapSize value of HeapSize option
+ * @param maxHeapSize value of MaxHeapSize option
+ * @param options additional options for JVM
+ * @param failureExpected true if JVM should fail with passed heap size options
+ */
+ public static void testXmnFlags(long mnValue,
+ long heapSize, long maxHeapSize,
+ LinkedList<String> options,
+ boolean failureExpected) throws Exception {
+ LinkedList<String> newOptions = new LinkedList<>(options);
+ newOptions.add("-Xmn" + mnValue);
+ testVMOptions(-1, -1,
+ heapSize, maxHeapSize,
+ mnValue, mnValue,
+ newOptions, failureExpected);
+ }
+
+ /**
+ * Verify that NewSize and MaxNewSize flags affect young gen size.
+ *
+ * @param newSize value of NewSize option, omitted if negative
+ * @param maxNewSize value of MaxNewSize option, omitted if negative
+ * @param heapSize value of HeapSize option
+ * @param maxHeapSize value of MaxHeapSize option
+ * @param expectedNewSize expected initial young gen size
+ * @param expectedMaxNewSize expected max young gen size
+ * @param options additional options for JVM
+ * @param failureExpected true if JVM should fail with passed heap size options
+ */
+ public static void testVMOptions(long newSize, long maxNewSize,
+ long heapSize, long maxHeapSize,
+ long expectedNewSize, long expectedMaxNewSize,
+ LinkedList<String> options, boolean failureExpected) throws Exception {
+ OutputAnalyzer analyzer = startVM(options, newSize, maxNewSize, heapSize, maxHeapSize, expectedNewSize, expectedMaxNewSize);
+
+ if (failureExpected) {
+ analyzer.shouldHaveExitValue(1);
+ analyzer.shouldMatch("(Error occurred during initialization of VM)|"
+ + "(Error: Could not create the Java Virtual Machine.)");
+ } else {
+ analyzer.shouldHaveExitValue(0);
+ }
+ }
+
+ private static OutputAnalyzer startVM(LinkedList<String> options,
+ long newSize, long maxNewSize,
+ long heapSize, long maxHeapSize,
+ long expectedNewSize, long expectedMaxNewSize) throws Exception, IOException {
+ LinkedList<String> vmOptions = new LinkedList<>(options);
+ Collections.addAll(vmOptions,
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ (newSize >= 0 ? "-XX:NewSize=" + newSize : ""),
+ (maxNewSize >= 0 ? "-XX:MaxNewSize=" + maxNewSize : ""),
+ "-Xmx" + maxHeapSize,
+ "-Xms" + heapSize,
+ "-XX:GCLockerEdenExpansionPercent=0",
+ "-XX:-UseLargePages",
+ NewSizeVerifier.class.getName(),
+ Long.toString(expectedNewSize),
+ Long.toString(expectedMaxNewSize)
+ );
+ vmOptions.removeIf(String::isEmpty);
+ ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+ OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+ return analyzer;
+ }
+
+ /**
+ * NewSizeVerifier checks that initial young gen size is equal to expected
+ * regardful to alignment and that young gen size will not be greater than
+ * expected max size.
+ * In order to verify that young gen size will not be greater then expected
+ * max size, NewSizeVerifier do some object allocation to force garbage
+ * collection and heap expansion.
+ */
+ public static class NewSizeVerifier {
+
+ static WhiteBox wb = WhiteBox.getWhiteBox();
+
+ public static final int ARRAY_LENGTH = 100;
+ public static final int CHUNK_SIZE = 1024;
+ public static final int MAX_ITERATIONS = 10;
+ public static byte garbage[][] = new byte[ARRAY_LENGTH][];
+
+ public static void main(String args[]) throws Exception {
+ if (args.length != 2) {
+ throw new IllegalArgumentException("Expected 2 args: <expectedNewSize> <expectedMaxNewSize>");
+ }
+ final long newSize = Long.valueOf(args[0]);
+ final long maxNewSize = Long.valueOf(args[1]);
+
+ // verify initial size
+ verifyNewSize(newSize, maxNewSize);
+
+ // force GC and verify that size is still correct
+ AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE, () -> (verifyNewSize(newSize, maxNewSize)));
+ allocator.allocateMemoryAndVerifyNoOOME();
+ }
+
+ /**
+ * Verify that actual young gen size conforms NewSize and MaxNewSize values.
+ */
+ public static Void verifyNewSize(long newSize, long maxNewSize) {
+ long alignedNewSize = alignNewSize(newSize);
+ long alignedMaxNewSize = alignNewSize(maxNewSize);
+
+ MemoryUsage youngGenUsage = getYoungGenUsage();
+
+ if (newSize != -1) {
+ if (youngGenUsage.getInit() < alignedNewSize) {
+ throw new RuntimeException("initial new size < NewSize value: "
+ + youngGenUsage.getInit() + " < " + alignedNewSize);
+ }
+
+ if (youngGenUsage.getCommitted() < alignedNewSize) {
+ throw new RuntimeException("actual new size < NewSize value: "
+ + youngGenUsage.getCommitted() + " < " + alignedNewSize);
+ }
+
+ // for G1 max new size == committed new size
+ if (GCTypes.YoungGCType.getYoungGCType() != GCTypes.YoungGCType.G1
+ && youngGenUsage.getMax() < alignedNewSize) {
+ throw new RuntimeException("max new size < NewSize value: "
+ + youngGenUsage.getMax() + " < " + alignedNewSize);
+ }
+ }
+
+ if (maxNewSize != -1) {
+ if (youngGenUsage.getInit() > alignedMaxNewSize) {
+ throw new RuntimeException("initial new size > MaxNewSize value: "
+ + youngGenUsage.getInit() + " > " + alignedMaxNewSize);
+ }
+
+ if (youngGenUsage.getCommitted() > alignedMaxNewSize) {
+ throw new RuntimeException("actual new size > MaxNewSize value: "
+ + youngGenUsage.getCommitted() + " > " + alignedMaxNewSize);
+ }
+
+ if (GCTypes.YoungGCType.getYoungGCType() != GCTypes.YoungGCType.G1
+ && youngGenUsage.getMax() != alignedMaxNewSize) {
+ throw new RuntimeException("max new size != MaxNewSize value: "
+ + youngGenUsage.getMax() + " != " + alignedMaxNewSize);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get young gen memory usage.
+ *
+ * For G1 it is EdenUsage + SurvivorUsage,
+ * for other GCs it is EdenUsage + 2 * SurvivorUsage.
+ * For G1 max value is just LONG_MAX.
+ * For all GCs used value is 0.
+ */
+ private static MemoryUsage getYoungGenUsage() {
+ if (GCTypes.YoungGCType.getYoungGCType() == GCTypes.YoungGCType.G1) {
+ return new MemoryUsage(HeapRegionUsageTool.getEdenUsage().getInit()
+ + HeapRegionUsageTool.getSurvivorUsage().getInit(),
+ 0,
+ HeapRegionUsageTool.getEdenUsage().getCommitted()
+ + HeapRegionUsageTool.getSurvivorUsage().getCommitted(),
+ Long.MAX_VALUE);
+ } else {
+ return new MemoryUsage(HeapRegionUsageTool.getEdenUsage().getInit()
+ + HeapRegionUsageTool.getSurvivorUsage().getInit() * 2,
+ 0,
+ HeapRegionUsageTool.getEdenUsage().getCommitted()
+ + HeapRegionUsageTool.getSurvivorUsage().getCommitted() * 2,
+ HeapRegionUsageTool.getEdenUsage().getMax()
+ + HeapRegionUsageTool.getSurvivorUsage().getMax() * 2);
+ }
+ }
+
+ /**
+ * Align value regardful to used young GC.
+ */
+ public static long alignNewSize(long value) {
+ switch (GCTypes.YoungGCType.getYoungGCType()) {
+ case DefNew:
+ case ParNew:
+ return HeapRegionUsageTool.alignDown(value, wb.getHeapSpaceAlignment());
+ case PSNew:
+ return HeapRegionUsageTool.alignUp(HeapRegionUsageTool.alignDown(value,
+ wb.getHeapSpaceAlignment()),
+ wb.psVirtualSpaceAlignment());
+ case G1:
+ return HeapRegionUsageTool.alignUp(value, wb.g1RegionSize());
+ default:
+ throw new RuntimeException("Unexpected young GC type");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 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.
+*/
+
+/*
+ * @test TestSurvivorRatioFlag
+ * @key gc
+ * @summary Verify that actual survivor ratio is equal to specified SurvivorRatio value
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.management
+ * @build TestSurvivorRatioFlag
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver TestSurvivorRatioFlag
+ */
+
+import jdk.test.lib.AllocationHelper;
+import java.lang.management.MemoryUsage;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import jdk.test.lib.HeapRegionUsageTool;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+public class TestSurvivorRatioFlag {
+
+ public static final long M = 1024 * 1024;
+ public static final long HEAP_SIZE = 200 * M;
+ public static final long NEW_SIZE = 100 * M;
+
+ public static void main(String args[]) throws Exception {
+ LinkedList<String> options = new LinkedList<>(
+ Arrays.asList(Utils.getFilteredTestJavaOpts("-XX:[^ ]*SurvivorRatio=[^ ]+"))
+ );
+
+ testSurvivorRatio(3, options);
+ testSurvivorRatio(6, options);
+ testSurvivorRatio(10, options);
+ testSurvivorRatio(15, options);
+ testSurvivorRatio(20, options);
+ }
+
+ /**
+ * Verify that actual survivor ratio equal to specified.
+ *
+ * @param ratio survivor ratio that be verified
+ * @param options additional options to JVM
+ */
+ public static void testSurvivorRatio(int ratio, LinkedList<String> options) throws Exception {
+
+ LinkedList<String> vmOptions = new LinkedList<>(options);
+
+ Collections.addAll(vmOptions,
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-XX:GCLockerEdenExpansionPercent=0",
+ "-XX:MaxNewSize=" + NEW_SIZE,
+ "-XX:NewSize=" + NEW_SIZE,
+ "-Xmx" + HEAP_SIZE,
+ "-Xms" + HEAP_SIZE,
+ "-XX:SurvivorRatio=" + ratio,
+ SurvivorRatioVerifier.class.getName(),
+ Integer.toString(ratio)
+ );
+
+ ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+ OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+ analyzer.shouldHaveExitValue(0);
+ }
+
+ /**
+ * Class that verifies survivor ratio.
+ */
+ public static class SurvivorRatioVerifier {
+
+ static WhiteBox wb = WhiteBox.getWhiteBox();
+
+ public static final int MAX_ITERATIONS = 10;
+ public static final int ARRAY_LENGTH = 10000;
+ public static final int CHUNK_SIZE = 10000;
+
+ public static void main(String args[]) throws Exception {
+ if (args.length != 1) {
+ throw new IllegalArgumentException("Expected 1 arg: <ratio>");
+ }
+ final int ratio = Integer.valueOf(args[0]);
+
+ AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE, () -> (verifySurvivorRatio(ratio)));
+ allocator.allocateMemoryAndVerify();
+ }
+
+ /**
+ * Verify that actual survivor ratio is equal to expected.
+ * Depending on selected young GC we verify that:
+ * - for DefNew and ParNew: eden_size / survivor_size is close to expectedRatio;
+ * - for PSNew: survivor_size equal to young_gen_size / expectedRatio;
+ * - for G1: survivor_regions <= young_list_length / expectedRatio.
+ */
+ public static Void verifySurvivorRatio(int expectedRatio) {
+ GCTypes.YoungGCType type = GCTypes.YoungGCType.getYoungGCType();
+ switch (type) {
+ case DefNew:
+ case ParNew:
+ verifyDefNewSurvivorRatio(expectedRatio);
+ break;
+ case PSNew:
+ verifyPSSurvivorRatio(expectedRatio);
+ break;
+ case G1:
+ verifyG1SurvivorRatio(expectedRatio);
+ break;
+ default:
+ throw new RuntimeException("Unexpected young GC type");
+ }
+ return null;
+ }
+
+ private static void verifyDefNewSurvivorRatio(int expectedRatio) {
+ MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage();
+ MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();
+
+ int actualRatio = (int) (edenUsage.getCommitted() / survivorUsage.getCommitted());
+ if (Math.abs(actualRatio - expectedRatio) > 1) {
+ throw new RuntimeException("Expected survivor ratio is: " + expectedRatio
+ + ", but observed ratio is: " + actualRatio);
+ }
+ }
+
+ private static void verifyPSSurvivorRatio(int expectedRatio) {
+ MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage();
+ MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();
+
+ long youngGenSize = edenUsage.getMax() + 2 * survivorUsage.getMax();
+ // for Paralle GC Min/InitialSurvivorRatio = SurvivorRatio + 2
+ long expectedSize = HeapRegionUsageTool.alignDown(youngGenSize / (expectedRatio + 2),
+ wb.psHeapGenerationAlignment());
+
+ if (expectedSize != survivorUsage.getCommitted()) {
+ throw new RuntimeException("Expected survivor size is: " + expectedSize
+ + ", but observed size is: " + survivorUsage.getCommitted());
+ }
+ }
+
+ private static void verifyG1SurvivorRatio(int expectedRatio) {
+ MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();
+
+ int regionSize = wb.g1RegionSize();
+ int youngListLength = (int) Math.max(NEW_SIZE / regionSize, 1);
+ int expectedSurvivorRegions = (int) Math.ceil(youngListLength / (double) expectedRatio);
+ int observedSurvivorRegions = (int) (survivorUsage.getCommitted() / regionSize);
+
+ if (expectedSurvivorRegions < observedSurvivorRegions) {
+ throw new RuntimeException("Expected amount of G1 survivor regions is "
+ + expectedSurvivorRegions + ", but observed "
+ + observedSurvivorRegions);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,319 @@
+/*
+* Copyright (c) 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.
+*/
+
+/*
+ * @test TestTargetSurvivorRatioFlag
+ * @key gc
+ * @summary Verify that option TargetSurvivorRatio affects survivor space occupancy after minor GC.
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ * java.management
+ * @build TestTargetSurvivorRatioFlag
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver TestTargetSurvivorRatioFlag
+ */
+
+import jdk.test.lib.AllocationHelper;
+import java.lang.management.GarbageCollectorMXBean;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import jdk.test.lib.HeapRegionUsageTool;
+import sun.misc.Unsafe;
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+/* In order to test that TargetSurvivorRatio affects survivor space occupancy
+ * we setup fixed MaxTenuringThreshold and then verifying that if size of allocated
+ * objects is lower than (survivor_size * TargetSurvivorRatio / 100) then objects
+ * will stay in survivor space until MaxTenuringThreshold minor GC cycles.
+ * If more than (survivor_size * TargetSurvivorRatio / 100) objects were allocated,
+ * then we verify that after MaxTenuringThreshold minor GC cycles survivor space
+ * is almost empty.
+ */
+public class TestTargetSurvivorRatioFlag {
+
+ public static final long M = 1024 * 1024;
+
+ // VM option values
+ public static final long MAX_NEW_SIZE = 40 * M;
+ public static final int SURVIVOR_RATIO = 8;
+ public static final int MAX_TENURING_THRESHOLD = 15;
+
+ // Value used to estimate amount of memory that should be allocated
+ // and placed in survivor space.
+ public static final double DELTA = 0.25;
+
+ // Max variance of observed ratio
+ public static double VARIANCE = 1;
+
+ // Messages used by debuggee
+ public static final String UNSUPPORTED_GC = "Unsupported GC";
+ public static final String START_TEST = "Start test";
+ public static final String END_TEST = "End test";
+
+ // Patterns used during log parsing
+ public static final String TENURING_DISTRIBUTION = "Desired survivor size";
+ public static final String AGE_TABLE_ENTRY = "-[\\s]+age[\\s]+([0-9]+):[\\s]+([0-9]+)[\\s]+bytes,[\\s]+([0-9]+)[\\s]+total";
+ public static final String MAX_SURVIVOR_SIZE = "Max survivor size: ([0-9]+)";
+
+ public static void main(String args[]) throws Exception {
+
+ LinkedList<String> options = new LinkedList<>(Arrays.asList(Utils.getTestJavaOpts()));
+
+ // Need to consider the effect of TargetPLABWastePct=1 for G1 GC
+ if (options.contains("-XX:+UseG1GC")) {
+ VARIANCE = 2;
+ } else {
+ VARIANCE = 1;
+ }
+
+ negativeTest(-1, options);
+ negativeTest(101, options);
+
+ positiveTest(20, options);
+ positiveTest(30, options);
+ positiveTest(55, options);
+ positiveTest(70, options);
+ }
+
+ /**
+ * Verify that VM will fail to start with specified TargetSurvivorRatio
+ *
+ * @param ratio value of TargetSurvivorRatio
+ * @param options additional VM options
+ */
+ public static void negativeTest(int ratio, LinkedList<String> options) throws Exception {
+ LinkedList<String> vmOptions = new LinkedList<>(options);
+ vmOptions.add("-XX:TargetSurvivorRatio=" + ratio);
+ vmOptions.add("-version");
+
+ ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+ OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+
+ analyzer.shouldHaveExitValue(1);
+ analyzer.shouldContain("Error: Could not create the Java Virtual Machine.");
+ }
+
+ /**
+ * Verify that actual survivor space usage ratio conforms specified TargetSurvivorRatio
+ *
+ * @param ratio value of TargetSurvivorRatio
+ * @param options additional VM options
+ */
+ public static void positiveTest(int ratio, LinkedList<String> options) throws Exception {
+ LinkedList<String> vmOptions = new LinkedList<>(options);
+ Collections.addAll(vmOptions,
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-XX:+UseAdaptiveSizePolicy",
+ "-XX:+PrintTenuringDistribution",
+ "-XX:MaxTenuringThreshold=" + MAX_TENURING_THRESHOLD,
+ "-XX:NewSize=" + MAX_NEW_SIZE,
+ "-XX:MaxNewSize=" + MAX_NEW_SIZE,
+ "-XX:InitialHeapSize=" + 2 * MAX_NEW_SIZE,
+ "-XX:MaxHeapSize=" + 2 * MAX_NEW_SIZE,
+ "-XX:SurvivorRatio=" + SURVIVOR_RATIO,
+ "-XX:TargetSurvivorRatio=" + ratio,
+ // For reducing variance of survivor size.
+ "-XX:TargetPLABWastePct=" + 1,
+ TargetSurvivorRatioVerifier.class.getName(),
+ Integer.toString(ratio)
+ );
+
+ ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
+ OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
+
+ analyzer.shouldHaveExitValue(0);
+
+ String output = analyzer.getOutput();
+
+ // Test avoids verification for parallel GC
+ if (!output.contains(UNSUPPORTED_GC)) {
+ // Two tests should be done - when actual ratio is lower than TargetSurvivorRatio
+ // and when it is higher. We chech that output contains results for exactly two tests.
+ List<Double> ratios = parseTestOutput(output);
+
+ if (ratios.size() != 2) {
+ System.out.println(output);
+ throw new RuntimeException("Expected number of ratios extraced for output is 2,"
+ + " but " + ratios.size() + " ratios were extracted");
+ }
+
+ // At the end of the first test survivor space usage ratio should lies between
+ // TargetSurvivorRatio and TargetSurvivorRatio - 2*DELTA
+ if (ratio < ratios.get(0) || ratio - ratios.get(0) > VARIANCE) {
+ System.out.println(output);
+ throw new RuntimeException("Survivor space usage ratio expected to be close to "
+ + ratio + ", but observed ratio is: " + ratios.get(0));
+ }
+
+ // After second test survivor space should be almost empty.
+ if (ratios.get(1) > VARIANCE) {
+ System.out.println(output);
+ throw new RuntimeException("Survivor space expected to be empty due to "
+ + "TargetSurvivorRatio overlimit, however observed "
+ + "survivor space usage ratio is: " + ratios.get(1));
+ }
+ } else {
+ System.out.println("Selected GC does not support TargetSurvivorRatio option.");
+ }
+ }
+
+ /**
+ * Parse output produced by TargetSurvivorRatioVerifier.
+ *
+ * @param output output obtained from TargetSurvivorRatioVerifier
+ * @return list of parsed test results, where each result is an actual
+ * survivor ratio after MaxTenuringThreshold minor GC cycles.
+ */
+ public static List<Double> parseTestOutput(String output) {
+ List<Double> ratios = new LinkedList<Double>();
+ String lines[] = output.split("[\n\r]");
+ boolean testStarted = false;
+ long survivorSize = 0;
+ long survivorOccupancy = 0;
+ int gcCount = 0;
+ Pattern ageTableEntry = Pattern.compile(AGE_TABLE_ENTRY);
+ Pattern maxSurvivorSize = Pattern.compile(MAX_SURVIVOR_SIZE);
+ for (String line : lines) {
+ if (Pattern.matches(MAX_SURVIVOR_SIZE, line)) {
+ // We found estimated survivor space size
+ Matcher m = maxSurvivorSize.matcher(line);
+ m.find();
+ survivorSize = Long.valueOf(m.group(1));
+ } else if (line.contains(START_TEST) && !testStarted) {
+ // Start collecting test results
+ testStarted = true;
+ gcCount = 0;
+ } else if (testStarted) {
+ if (line.contains(TENURING_DISTRIBUTION)) {
+ // We found start of output emitted by -XX:+PrintTenuringDistribution
+ // If it is associated with "MaxTenuringThreshold" GC cycle, then it's
+ // time to report observed survivor usage ratio
+ gcCount++;
+ double survivorRatio = survivorOccupancy / (double) survivorSize;
+ if (gcCount == MAX_TENURING_THRESHOLD || gcCount == MAX_TENURING_THRESHOLD * 2) {
+ ratios.add(survivorRatio * 100.0);
+ testStarted = false;
+ }
+ survivorOccupancy = 0;
+ } else if (Pattern.matches(AGE_TABLE_ENTRY, line)) {
+ // Obtain survivor space usage from "total" age table log entry
+ Matcher m = ageTableEntry.matcher(line);
+ m.find();
+ survivorOccupancy = Long.valueOf(m.group(3));
+ } else if (line.contains(END_TEST)) {
+ // It is expected to find at least MaxTenuringThreshold GC events
+ // until test end
+ if (gcCount < MAX_TENURING_THRESHOLD) {
+ throw new RuntimeException("Observed " + gcCount + " GC events, "
+ + "while it is expected to see at least "
+ + MAX_TENURING_THRESHOLD);
+ }
+ testStarted = false;
+ }
+ }
+ }
+ return ratios;
+ }
+
+ public static class TargetSurvivorRatioVerifier {
+
+ static final WhiteBox wb = WhiteBox.getWhiteBox();
+ static final Unsafe unsafe = Utils.getUnsafe();
+
+ // Desired size of memory allocated at once
+ public static final int CHUNK_SIZE = 1024;
+ // Length of byte[] array that will have occupy CHUNK_SIZE bytes in heap
+ public static final int ARRAY_LENGTH = CHUNK_SIZE - Unsafe.ARRAY_BYTE_BASE_OFFSET;
+
+ public static void main(String args[]) throws Exception {
+ if (args.length != 1) {
+ throw new IllegalArgumentException("Expected 1 arg: <ratio>");
+ }
+ if (GCTypes.YoungGCType.getYoungGCType() == GCTypes.YoungGCType.PSNew) {
+ System.out.println(UNSUPPORTED_GC);
+ return;
+ }
+
+ int ratio = Integer.valueOf(args[0]);
+ long maxSurvivorSize = getMaxSurvivorSize();
+ System.out.println("Max survivor size: " + maxSurvivorSize);
+
+ allocateMemory(ratio - DELTA, maxSurvivorSize);
+ allocateMemory(ratio + DELTA, maxSurvivorSize);
+ }
+
+ /**
+ * Allocate (<b>ratio</b> * <b>maxSize</b> / 100) bytes of objects
+ * and force at least "MaxTenuringThreshold" minor GCs.
+ *
+ * @param ratio ratio used to calculate how many objects should be allocated
+ * @param maxSize estimated max survivor space size
+ */
+ public static void allocateMemory(double ratio, long maxSize) throws Exception {
+ GarbageCollectorMXBean youngGCBean = GCTypes.YoungGCType.getYoungGCBean();
+ long garbageSize = (long) (maxSize * (ratio / 100.0));
+ int arrayLength = (int) (garbageSize / CHUNK_SIZE);
+ AllocationHelper allocator = new AllocationHelper(1, arrayLength, ARRAY_LENGTH, null);
+
+ System.out.println(START_TEST);
+ System.gc();
+ final long initialGcId = youngGCBean.getCollectionCount();
+ // allocate memory
+ allocator.allocateMemoryAndVerify();
+
+ // force minor GC
+ while (youngGCBean.getCollectionCount() <= initialGcId + MAX_TENURING_THRESHOLD * 2) {
+ byte b[] = new byte[ARRAY_LENGTH];
+ }
+
+ allocator.release();
+ System.out.println(END_TEST);
+ }
+
+ /**
+ * Estimate max survivor space size.
+ *
+ * For non-G1 GC returns value reported by MemoryPoolMXBean
+ * associated with survivor space.
+ * For G1 GC return max number of survivor regions * region size.
+ * Number if survivor regions estimated from MaxNewSize and SurvivorRatio.
+ */
+ public static long getMaxSurvivorSize() {
+ if (GCTypes.YoungGCType.getYoungGCType() == GCTypes.YoungGCType.G1) {
+ int youngLength = (int) Math.max(MAX_NEW_SIZE / wb.g1RegionSize(), 1);
+ return (long) Math.ceil(youngLength / (double) SURVIVOR_RATIO) * wb.g1RegionSize();
+ } else {
+ return HeapRegionUsageTool.getSurvivorUsage().getMax();
+ }
+ }
+ }
+}
--- a/hotspot/test/gc/g1/TestHumongousShrinkHeap.java Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/test/gc/g1/TestHumongousShrinkHeap.java Mon Sep 14 07:03:04 2015 +0000
@@ -58,6 +58,10 @@
public static void main(String[] args) {
+ if (HUMON_COUNT == 0) {
+ System.out.println("Skipped. Heap is too small");
+ return;
+ }
System.out.format("Running with %s max heap size. "
+ "Will allocate humongous object of %s size %d times.%n",
MemoryUsagePrinter.humanReadableByteCount(AVAILABLE_MEMORY, false),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestPLABSizeBounds.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestPLABSizeBounds
+ * @bug 8134857
+ * @summary Regression test to ensure that G1 supports PLAB sizes of half a region size.
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @key gc
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.management
+ */
+
+import java.util.ArrayList;
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.Platform;
+import jdk.test.lib.ProcessTools;
+
+public class TestPLABSizeBounds {
+
+ public static final int M = 1024 * 1024;
+
+ /**
+ * Starts the VM with the given region size and the given PLAB size arguments. The VM start should
+ * succeed if shouldSucceed is true, otherwise it should fail.
+ *
+ * @param regionSize The region size the VM should be started with in bytes.
+ * @param plabSize The young and old gen PLAB sizes the VM should be started with in machine words.
+ * @param shouldSucceed The expected result of the VM invocation.
+ */
+ public static void runTest(int regionSize, int plabSize, boolean shouldSucceed) throws Exception {
+ ArrayList<String> testArguments = new ArrayList<String>();
+
+ testArguments.add("-XX:+UseG1GC");
+ testArguments.add("-Xmx256M");
+ testArguments.add("-XX:G1HeapRegionSize=" + regionSize);
+ testArguments.add("-XX:YoungPLABSize=" + plabSize);
+ testArguments.add("-XX:OldPLABSize=" + plabSize);
+ testArguments.add(GCTest.class.getName());
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(testArguments.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ if (shouldSucceed) {
+ output.shouldHaveExitValue(0);
+ } else {
+ output.shouldHaveExitValue(1);
+ }
+ }
+
+ public static void runRegionTest(int regionSize) throws Exception {
+ final int regionSizeInBytes = regionSize * M;
+ final int wordSize = Platform.is32bit() ? 4 : 8;
+
+ runTest(regionSizeInBytes, (regionSizeInBytes / wordSize) / 2 - 1, true);
+ runTest(regionSizeInBytes, (regionSizeInBytes / wordSize) / 2, true);
+ runTest(regionSizeInBytes, (regionSizeInBytes / wordSize) / 2 + 1, false);
+ }
+
+ public static void main(String[] args) throws Exception {
+ runRegionTest(1);
+ runRegionTest(2);
+ runRegionTest(4);
+ runRegionTest(8);
+ runRegionTest(16);
+ runRegionTest(32);
+ }
+
+ static class GCTest {
+ public static void main(String [] args) {
+ System.out.println("Test completed.");
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/humongousObjects/Helpers.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 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 gc.g1.humongousObjects;
+
+import sun.hotspot.WhiteBox;
+
+public class Helpers {
+
+ // In case of 128 byte padding
+ private static final int MAX_PADDING_SIZE = 128;
+
+ /**
+ * Detects amount of extra bytes required to allocate a byte array.
+ * Allocating a byte[n] array takes more then just n bytes in the heap.
+ * Extra bytes are required to store object reference and the length.
+ * This amount depends on bitness and other factors.
+ *
+ * @return byte[] memory overhead
+ */
+ public static int detectByteArrayAllocationOverhead() {
+
+ WhiteBox whiteBox = WhiteBox.getWhiteBox();
+
+ int zeroLengthByteArraySize = (int) whiteBox.getObjectSize(new byte[0]);
+
+ // Since we do not know is there any padding in zeroLengthByteArraySize we cannot just take byte[0] size as overhead
+ for (int i = 1; i < MAX_PADDING_SIZE + 1; ++i) {
+ int realAllocationSize = (int) whiteBox.getObjectSize(new byte[i]);
+ if (realAllocationSize != zeroLengthByteArraySize) {
+ // It means we did not have any padding on previous step
+ return zeroLengthByteArraySize - (i - 1);
+ }
+ }
+ throw new Error("We cannot find byte[] memory overhead - should not reach here");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 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 gc.g1.humongousObjects;
+
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+/**
+ * @test TestHumongousThreshold
+ * @summary Checks that objects larger than half a region are allocated as humongous
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @library /testlibrary /../../test/lib
+ * @modules java.management
+ * @build sun.hotspot.WhiteBox
+ * gc.g1.humongousObjects.Helpers
+ * gc.g1.humongousObjects.TestHumongousThreshold
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=1M
+ * gc.g1.humongousObjects.TestHumongousThreshold
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=2M
+ * gc.g1.humongousObjects.TestHumongousThreshold
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=4M
+ * gc.g1.humongousObjects.TestHumongousThreshold
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=8M
+ * gc.g1.humongousObjects.TestHumongousThreshold
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=16M
+ * gc.g1.humongousObjects.TestHumongousThreshold
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:G1HeapRegionSize=32M
+ * gc.g1.humongousObjects.TestHumongousThreshold
+ *
+ */
+
+public class TestHumongousThreshold {
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ private static final int REGION_SIZE = WHITE_BOX.g1RegionSize();
+ private static final int MAX_CONTINUOUS_SIZE_CHECK = 129;
+ private static final int NON_HUMONGOUS_DIVIDER = 10;
+
+ /**
+ * The method allocates byte[] with specified size and checks that:
+ * 1. byte[] is allocated as we specified in expectedHumongous.
+ * 2. byte[] is allocated as humongous if its size is large than a half of region and non-humongous otherwise.
+ * It uses WB to obtain the size of created byte[]. Only objects larger than half of region are expected
+ * to be humongous.
+ *
+ * @param arraySize size of allocation
+ * @param expectedHumongous expected humongous/non-humongous allocation
+ * @return allocated byte array
+ */
+
+ private static byte[] allocateAndCheck(int arraySize, boolean expectedHumongous) {
+ byte[] storage = new byte[arraySize];
+ long objectSize = WHITE_BOX.getObjectSize(storage);
+ boolean shouldBeHumongous = objectSize > (REGION_SIZE / 2);
+
+ Asserts.assertEquals(expectedHumongous, shouldBeHumongous, "Despite we expected this object to be "
+ + (expectedHumongous ? "humongous" : "non-humongous") + " it appeared otherwise when we checked "
+ + "object size - likely test bug; Allocation size = " + arraySize + "; Object size = " + objectSize
+ + "; region size = " + REGION_SIZE);
+
+ Asserts.assertEquals(WHITE_BOX.g1IsHumongous(storage), shouldBeHumongous,
+ "Object should be allocated as " + (shouldBeHumongous ? "humongous"
+ : "non-humongous") + " but it wasn't; Allocation size = " + arraySize + "; Object size = "
+ + objectSize + "; region size = " + REGION_SIZE);
+ return storage;
+ }
+
+ public static void main(String[] args) {
+ int byteArrayMemoryOverhead = Helpers.detectByteArrayAllocationOverhead();
+
+ // Largest non-humongous byte[]
+ int maxByteArrayNonHumongousSize = (REGION_SIZE / 2) - byteArrayMemoryOverhead;
+
+ // Increment for non-humongous testing
+ int nonHumongousStep = maxByteArrayNonHumongousSize / NON_HUMONGOUS_DIVIDER;
+
+ // Maximum byte[] that takes one region
+ int maxByteArrayOneRegionSize = REGION_SIZE - byteArrayMemoryOverhead;
+
+ // Sizes in regions
+ // i,e, 1.0f means one region, 1.5f means one and half region etc
+ float[] humongousFactors = {0.8f, 1.0f, 1.2f, 1.5f, 1.7f, 2.0f, 2.5f};
+
+ // Some diagnostic output
+ System.out.format("%s started%n", TestHumongousThreshold.class.getName());
+ System.out.format("Actual G1 region size %d%n", REGION_SIZE);
+ System.out.format("byte[] memory overhead %d%n", byteArrayMemoryOverhead);
+
+ // Non-humongous allocations
+ System.out.format("Doing non-humongous allocations%n");
+
+ // Testing allocations with byte[] with length from 0 to MAX_CONTINUOUS_SIZE_CHECK
+ System.out.format("Testing allocations with byte[] with length from 0 to %d%n", MAX_CONTINUOUS_SIZE_CHECK);
+ for (int i = 0; i < MAX_CONTINUOUS_SIZE_CHECK; ++i) {
+ allocateAndCheck(i, false);
+ }
+
+ // Testing allocations with byte[] with length from 0 to nonHumongousStep * NON_HUMONGOUS_DIVIDER
+ System.out.format("Testing allocations with byte[] with length from 0 to %d with step %d%n",
+ nonHumongousStep * NON_HUMONGOUS_DIVIDER, nonHumongousStep);
+ for (int i = 0; i < NON_HUMONGOUS_DIVIDER; ++i) {
+ allocateAndCheck(i * nonHumongousStep, false);
+ }
+
+ // Testing allocations with byte[] of maximum non-humongous length
+ System.out.format("Testing allocations with byte[] of maximum non-humongous length %d%n",
+ maxByteArrayNonHumongousSize);
+ allocateAndCheck(maxByteArrayNonHumongousSize, false);
+
+ // Humongous allocations
+ System.out.format("Doing humongous allocations%n");
+ // Testing with minimum humongous object
+ System.out.format("Testing with byte[] of minimum humongous object %d%n", maxByteArrayNonHumongousSize + 1);
+ allocateAndCheck(maxByteArrayNonHumongousSize + 1, true);
+
+ // Testing allocations with byte[] with length from (maxByteArrayNonHumongousSize + 1) to
+ // (maxByteArrayNonHumongousSize + 1 + MAX_CONTINUOUS_SIZE_CHECK)
+ System.out.format("Testing allocations with byte[] with length from %d to %d%n",
+ maxByteArrayNonHumongousSize + 1, maxByteArrayNonHumongousSize + 1 + MAX_CONTINUOUS_SIZE_CHECK);
+ for (int i = 0; i < MAX_CONTINUOUS_SIZE_CHECK; ++i) {
+ allocateAndCheck(maxByteArrayNonHumongousSize + 1 + i, true);
+ }
+
+ // Checking that large (more than a half of region size) objects are humongous
+ System.out.format("Checking that large (more than a half of region size) objects are humongous%n");
+ for (float factor : humongousFactors) {
+ allocateAndCheck((int) (maxByteArrayOneRegionSize * factor), true);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/logging/TestPrintReferences.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestPrintReferences
+ * @bug 8133818
+ * @summary Validate the reference processing logging
+ * @key gc
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.management
+ */
+
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.OutputAnalyzer;
+
+public class TestPrintReferences {
+ public static void main(String[] args) throws Exception {
+ ProcessBuilder pb_enabled =
+ ProcessTools.createJavaProcessBuilder("-XX:+PrintGCDetails", "-XX:+PrintReferenceGC", "-Xmx10M", GCTest.class.getName());
+ OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start());
+
+ output.shouldMatch(
+ "#[0-9]+: \\[SoftReference, [0-9]+ refs, [0-9]+\\.[0-9]+ secs\\]" +
+ "#[0-9]+: \\[WeakReference, [0-9]+ refs, [0-9]+\\.[0-9]+ secs\\]" +
+ "#[0-9]+: \\[FinalReference, [0-9]+ refs, [0-9]+\\.[0-9]+ secs\\]" +
+ "#[0-9]+: \\[PhantomReference, [0-9]+ refs, [0-9]+\\.[0-9]+ secs\\]" +
+ "#[0-9]+: \\[Cleaners, [0-9]+ refs, [0-9]+\\.[0-9]+ secs\\]" +
+ "#[0-9]+: \\[JNI Weak Reference, [0-9]+ refs, [0-9]+\\.[0-9]+ secs\\]");
+
+ output.shouldHaveExitValue(0);
+ }
+
+ static class GCTest {
+ public static void main(String [] args) {
+ System.gc();
+ }
+ }
+}
--- a/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java Mon Sep 14 07:03:04 2015 +0000
@@ -35,14 +35,14 @@
import java.util.ArrayList;
import sun.tools.jar.Main;
+// Using JarBuilder requires that all to-be-jarred classes should be placed
+// in the current working directory, aka "."
public class BasicJarBuilder {
private static final String classDir = System.getProperty("test.classes");
- public static void build(String jarName, String ...classNames)
- throws Exception {
-
- createSimpleJar(classDir, classDir + File.separator + jarName +
- ".jar", classNames);
+ public static void build(String jarName, String ...classNames) throws Exception {
+ createSimpleJar(".", classDir + File.separator + jarName + ".jar",
+ classNames);
}
private static void createSimpleJar(String jarclassDir, String jarName,
@@ -71,7 +71,7 @@
}
}
- // helpers
+ // Get full path to the test jar
public static String getTestJar(String jar) {
File dir = new File(System.getProperty("test.classes", "."));
File jarFile = new File(dir, jar);
--- a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java Mon Sep 14 07:03:04 2015 +0000
@@ -32,12 +32,10 @@
* @library /testlibrary /../../test/lib
* @modules java.base/sun.misc
* java.management
- * @ignore - 8133180
- * @build SharedStringsWb SharedStrings BasicJarBuilder
+ * @build SharedStringsWb SharedStrings BasicJarBuilder sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main SharedStrings
*/
-
import jdk.test.lib.*;
public class SharedStrings {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStringsRunAuto.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test SharedStringsAuto
+ * @summary Test -Xshare:auto with shared strings.
+ * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
+ * @requires (sun.arch.data.model != "32") & (os.family != "windows")
+ * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
+ * @requires (vm.gc=="G1" | vm.gc=="null")
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.management
+ * @run main SharedStringsRunAuto
+ */
+
+import jdk.test.lib.*;
+import java.io.File;
+
+public class SharedStringsRunAuto {
+ public static void main(String[] args) throws Exception {
+ // Dump
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=./SharedStringsRunAuto.jsa",
+ "-XX:+UseCompressedOops", "-XX:+UseG1GC",
+ "-XX:+PrintSharedSpaces",
+ "-Xshare:dump");
+
+ new OutputAnalyzer(pb.start())
+ .shouldContain("Loading classes to share")
+ .shouldContain("Shared string table stats")
+ .shouldHaveExitValue(0);
+
+ // Run with -Xshare:auto
+ pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=./SharedStringsRunAuto.jsa",
+ "-XX:+UseCompressedOops", "-XX:+UseG1GC",
+ "-Xshare:auto",
+ "-version");
+
+ new OutputAnalyzer(pb.start())
+ .shouldMatch("(java|openjdk) version")
+ .shouldHaveExitValue(0);
+ }
+}
--- a/hotspot/test/runtime/SharedArchiveFile/SharedStringsWb.java Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStringsWb.java Mon Sep 14 07:03:04 2015 +0000
@@ -34,8 +34,8 @@
return;
}
- // The string "java" is known to be interened and added to CDS archive
- String s = "java";
+ // The string below is known to be added to CDS archive
+ String s = "<init>";
String internedS = s.intern();
if (wb.isShared(internedS)) {
--- a/hotspot/test/runtime/modules/ImageFile/ImageAttributeOffsetsTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Retrieves the array of offsets once with MemoryMapImage enabled once disabled.
- * @test ImageAttributeOffsetsTest
- * @summary Unit test for JVM_ImageAttributeOffsets() method
- * @library /testlibrary /../../test/lib
- * @build ImageAttributeOffsetsTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageAttributeOffsetsTest
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageAttributeOffsetsTest
- */
-
-import java.io.File;
-import java.nio.ByteOrder;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageAttributeOffsetsTest {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String imageFile = javaHome + File.separator + "lib" + File.separator
- + "modules" + File.separator + "bootmodules.jimage";
-
- if (!(new File(imageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
- long id = wb.imageOpenImage(imageFile, bigEndian);
- boolean passed = true;
- // Get offsets
- int[] array = wb.imageAttributeOffsets(id);
- assertNotNull(array, "Could not retrieve offsets of array");
-
- wb.imageCloseImage(id);
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageCloseTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Test closing image opened multiple time. Test closing mutiple time an image.
- * @test ImageCloseTest
- * @summary Unit test for JVM_ImageClose() method
- * @library /testlibrary /../../test/lib
- * @build ImageCloseTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageCloseTest
- */
-
-import java.io.File;
-import java.nio.ByteOrder;
-import sun.hotspot.WhiteBox;
-
-public class ImageCloseTest {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String imageFile = javaHome + File.separator + "lib" + File.separator
- + "modules" + File.separator + "bootmodules.jimage";
-
- if (!(new File(imageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
- long id = 0;
-
- // too many opens
- for (int i = 0; i < 100; i++) {
- id = wb.imageOpenImage(imageFile, bigEndian);
- }
- wb.imageCloseImage(id);
-
- // too many closes
- id = wb.imageOpenImage(imageFile, bigEndian);
- for (int i = 0; i < 100; i++) {
- wb.imageCloseImage(id);
- }
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageFileHeaderTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Test that opening image containing wrong headers fails.
- * @test ImageFileHeaderTest
- * @library /testlibrary /../../test/lib
- * @build ImageFileHeaderTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageFileHeaderTest
- */
-
-import java.nio.*;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageFileHeaderTest {
-
- public static final int MAGIC = 0xCAFEDADA;
- public static final short MAJOR = 0;
- public static final short MINOR = 1;
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
- public static ByteBuffer buf;
-
- public static void main(String... args) throws Exception {
-
- ByteOrder endian = getEndian();
-
- // Try to read a non-existing file
- assertFalse(wb.readImageFile("bogus"));
-
- // Incomplete header, only include the correct magic
- buf = ByteBuffer.allocate(100);
- buf.order(endian);
- buf.putInt(MAGIC);
- assertFalse(testImageFile("invalidheader.jimage"));
-
- // Build a complete header but reverse the endian
- buf = ByteBuffer.allocate(100);
- buf.order(endian == ByteOrder.LITTLE_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
- buf.putInt(MAGIC);
- buf.putShort(MAJOR);
- buf.putShort(MINOR);
- assertFalse(testImageFile("wrongendian.jimage"));
-
- // Use the wrong magic
- buf = ByteBuffer.allocate(100);
- buf.order(endian);
- buf.putInt(0xBEEFCACE);
- buf.putShort(MAJOR);
- buf.putShort(MINOR);
- assertFalse(testImageFile("wrongmagic.jimage"));
-
- // Wrong major version (current + 1)
- buf = ByteBuffer.allocate(100);
- buf.order(endian);
- buf.putInt(MAGIC);
- buf.putShort((short)(MAJOR + 1));
- buf.putShort((short)MINOR);
- assertFalse(testImageFile("wrongmajorversion.jimage"));
-
- // Wrong major version (negative)
- buf = ByteBuffer.allocate(100);
- buf.order(endian);
- buf.putInt(MAGIC);
- buf.putShort((short) -17);
- buf.putShort((short)MINOR);
- assertFalse(testImageFile("negativemajorversion.jimage"));
-
- // Wrong minor version (current + 1)
- buf = ByteBuffer.allocate(100);
- buf.order(endian);
- buf.putInt(MAGIC);
- buf.putShort((short)MAJOR);
- buf.putShort((short)(MINOR + 1));
- assertFalse(testImageFile("wrongminorversion.jimage"));
-
- // Wrong minor version (negative)
- buf = ByteBuffer.allocate(100);
- buf.order(endian);
- buf.putInt(MAGIC);
- buf.putShort((short)MAJOR);
- buf.putShort((short) -17);
- assertFalse(testImageFile("negativeminorversion.jimage"));
- }
-
- public static boolean testImageFile(String filename) throws Exception {
- Files.write(Paths.get(filename), buf.array());
- System.out.println("Calling ReadImageFile on " + filename);
- return wb.readImageFile(filename);
- }
-
- public static ByteOrder getEndian() {
- String endian = System.getProperty("sun.cpu.endian");
- if (endian.equalsIgnoreCase("little")) {
- return ByteOrder.LITTLE_ENDIAN;
- } else if (endian.equalsIgnoreCase("big")) {
- return ByteOrder.BIG_ENDIAN;
- }
- throw new RuntimeException("Unexpected sun.cpu.endian value: " + endian);
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageFindAttributesTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Find the attributes of existing and invalid classes.
- * @test ImageFindAttributesTest
- * @summary Unit test for JVM_ImageFindAttributes() method
- * @library /testlibrary /../../test/lib
- * @build ImageFindAttributesTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageFindAttributesTest
- */
-
-import java.io.File;
-import java.nio.ByteOrder;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageFindAttributesTest {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String imageFile = javaHome + File.separator + "lib" + File.separator
- + "modules" + File.separator + "bootmodules.jimage";
-
- if (!(new File(imageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
- long id = wb.imageOpenImage(imageFile, bigEndian);
-
- // class resource
- String className = "/java.base/java/lang/String.class";
- long[] longArr = wb.imageFindAttributes(id, className.getBytes());
-
- assertNotNull(longArr, "Could not retrieve attributes of class " + className);
-
- // non-existent resource
- String neClassName = "/java.base/java/lang/NonExistentClass.class";
- longArr = wb.imageFindAttributes(id, neClassName.getBytes());
-
- assertNull(longArr, "Failed. Returned not null for non-existent " + neClassName);
-
- // garbage byte array
- byte[] buf = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- longArr = wb.imageFindAttributes(id, buf);
-
- assertNull(longArr, "Found attributes for garbage class");
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageGetAttributesTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Test getting all attributes,
- * @test ImageGetAttributesTest
- * @summary Unit test for JVM_ImageGetAttributes() method
- * @library /testlibrary /../../test/lib
- * @build LocationConstants ImageGetAttributesTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetAttributesTest
- */
-
-import java.io.File;
-import java.nio.ByteOrder;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageGetAttributesTest implements LocationConstants {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String imageFile = javaHome + File.separator + "lib" + File.separator
- + "modules" + File.separator + "bootmodules.jimage";
-
- if (!(new File(imageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- testImageGetAttributes(imageFile);
- }
-
- private static void testImageGetAttributes(String imageFile) {
-
- boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
- long id = wb.imageOpenImage(imageFile, bigEndian);
- try {
- long stringsSize = wb.imageGetStringsSize(id);
- assertNE(stringsSize, 0, "strings size is 0");
-
- int[] array = wb.imageAttributeOffsets(id);
- assertNotNull(array, "Could not retrieve offsets of array");
-
- // Get non-null attributes
- boolean attFound = false;
- int[] idx = {-1, -1, -1};
- // first non-null attribute
- for (int i = 0; i < array.length; i++) {
- if (array[i] != 0) {
- attFound = true;
- idx[0] = i;
- break;
- }
- }
-
- // middle non-null attribute
- for (int i = array.length / 2; i < array.length; i++) {
- if (array[i] != 0) {
- attFound = true;
- idx[1] = i;
- break;
- }
- }
-
- // last non-null attribute
- for (int i = array.length - 1; i >= 0; i--) {
- if (array[i] != 0) {
- attFound = true;
- idx[2] = i;
- break;
- }
- }
- assertTrue(attFound, "Failed. No non-null offset attributes");
- // test cases above
- for (int i = 0; i < 3; i++) {
- if (idx[i] != -1) {
- long[] attrs = wb.imageGetAttributes(id, (int) array[idx[i]]);
- long module = attrs[LOCATION_ATTRIBUTE_MODULE];
- long parent = attrs[LOCATION_ATTRIBUTE_PARENT];
- long base = attrs[LOCATION_ATTRIBUTE_BASE];
- long ext = attrs[LOCATION_ATTRIBUTE_EXTENSION];
-
- if ((module >= 0) && (module < stringsSize)
- && (parent >= 0) && (parent < stringsSize)
- && (base != 0)
- && (ext >= 0) && (ext < stringsSize)) {
- } else {
- System.out.printf("Failed. Read attribute offset %d (position %d) but wrong offsets\n",
- array[idx[i]], idx[i]);
- System.out.printf(" offsets: module = %d parent = %d base = %d extention = %d\n",
- module, parent, base, ext);
- throw new RuntimeException("Read attribute offset error");
- }
- } else {
- System.out.printf("Failed. Could not read attribute offset %d (position %d)\n",
- array[idx[i]], idx[i]);
- throw new RuntimeException("Read attribute offset error");
- }
- }
- } finally {
- wb.imageCloseImage(id);
- }
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageGetDataAddressTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Test accessing the data address of a jimage. This only makes sense when the
- * entire jimage is mapped into memory.
- * @test ImageGetDataAddressTest
- * @summary Unit test for JVM_ImageGetDataAddress() method
- * @library /testlibrary /../../test/lib
- * @build ImageGetDataAddressTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageGetDataAddressTest +
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageGetDataAddressTest -
- */
-
-import java.io.File;
-import java.nio.ByteOrder;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageGetDataAddressTest {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String imageFile = javaHome + File.separator + "lib" + File.separator
- + "modules" + File.separator + "bootmodules.jimage";
-
- if (!(new File(imageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- boolean isMMap = args[0].equals("+");
-
- boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
- long id = wb.imageOpenImage(imageFile, bigEndian);
-
- // get data for valid id
- long dataAddr = wb.imageGetDataAddress(id);
- assertFalse((dataAddr == 0) && isMMap, "Failed. Data address is " + dataAddr + " for valid id\n");
-
- // get data for invalid id == 0
- dataAddr = wb.imageGetDataAddress(0);
- assertTrue(dataAddr == 0, "Failed. Data address is " + dataAddr + " for zero id\n");
-
- wb.imageCloseImage(id);
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageGetIndexAddressTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Test the address of the jimage index.
- * @test ImageGetIndexAddressTest
- * @summary Unit test for JVM_ImageGetIndexAddress() method
- * @library /testlibrary /../../test/lib
- * @build ImageGetIndexAddressTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetIndexAddressTest
- */
-
-import java.io.File;
-import java.nio.ByteOrder;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageGetIndexAddressTest {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String imageFile = javaHome + File.separator + "lib" + File.separator
- + "modules" + File.separator + "bootmodules.jimage";
-
- if (!(new File(imageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
- long id = wb.imageOpenImage(imageFile, bigEndian);
-
- // get index for valid id
- long indexAddr = wb.imageGetIndexAddress(id);
- assertFalse(indexAddr == 0, "Failed. Index address is zero for valid id");
-
- // get index for invalid id == 0
- indexAddr = wb.imageGetIndexAddress(0);
- assertTrue(indexAddr == 0, "Failed. Index address is" + indexAddr + " for zero id\n");
-
- wb.imageCloseImage(id);
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageGetStringBytesTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Test that the string referenced by an attribute is retrieved.
- * @test ImageGetStringBytesTest
- * @summary Unit test for JVM_ImageGetStringBytes() method
- * @library /testlibrary /../../test/lib
- * @build LocationConstants ImageGetStringBytesTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetStringBytesTest
- */
-
-import java.io.File;
-import java.nio.ByteOrder;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageGetStringBytesTest implements LocationConstants {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String imageFile = javaHome + File.separator + "lib" + File.separator
- + "modules" + File.separator + "bootmodules.jimage";
-
- if (!(new File(imageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
- long id = wb.imageOpenImage(imageFile, bigEndian);
-
- String className = "/java.base/java/lang/String.class";
- long[] offsetArr = wb.imageFindAttributes(id, className.getBytes());
-
- // Module
- assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_MODULE, "Module"));
-
- // Parent
- assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_PARENT, "Parent"));
-
- // Base
- assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_BASE, "Base"));
-
- // Extension
- assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_EXTENSION, "Extension"));
-
- wb.imageCloseImage(id);
- }
-
- private static boolean checkAttribute(long id, long[] offsetArr, int attrId, String attrName) {
- long offset = offsetArr[attrId];
- return wb.imageGetStringBytes(id, (int) offset) != null;
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageOpenTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Test image opening/closing
- * @test ImageOpenTest
- * @summary Unit test for JVM_ImageOpen() method
- * @library /testlibrary /../../test/lib
- * @build ImageOpenTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageOpenTest
- */
-
-import java.io.File;
-import java.nio.ByteOrder;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageOpenTest {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String nonexistentImageFile = javaHome + "/lib/modules/nonexistent.jimage";
- String bootmodulesImageFile = javaHome + File.separator + "lib" + File.separator
- + "modules" + File.separator + "bootmodules.jimage";
-
- if (!(new File(bootmodulesImageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
-
- // open nonexistent image
- long id = wb.imageOpenImage(nonexistentImageFile, bigEndian);
- assertTrue(id == 0L, "Failed. Get id " + id + "instead of 0 on opening nonexistent file\n");
- wb.imageCloseImage(id);
-
- // open bootmodules image
- id = wb.imageOpenImage(bootmodulesImageFile, bigEndian);
- assertFalse(id == 0, "Failed. Get id 0 on opening bootmodules.jimage");
- wb.imageCloseImage(id);
-
- // non-native endian
- id = wb.imageOpenImage(bootmodulesImageFile, !bigEndian);
- assertFalse(id == 0, "Failed. Get id 0 on opening bootmodules.jimage with non-native endian");
- wb.imageCloseImage(id);
-
- //
- // open several times
- //
- id = wb.imageOpenImage(bootmodulesImageFile, bigEndian);
- long id1 = wb.imageOpenImage(bootmodulesImageFile, bigEndian);
- long id2 = wb.imageOpenImage(bootmodulesImageFile, bigEndian);
- assertTrue((id == id1) && (id == id2), "Failed. Open thee times with ids " + id + " " + id1 + " " + id1);
-
- wb.imageCloseImage(id);
- wb.imageCloseImage(id1);
- wb.imageCloseImage(id2);
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/ImageReadTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-/*
- * Test reading resource content.
- * @test ImageReadTest
- * @summary Unit test for JVM_ImageRead() method
- * @library /testlibrary /../../test/lib
- * @build LocationConstants ImageReadTest
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageReadTest +
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageReadTest -
- */
-
-import java.io.File;
-import java.nio.ByteBuffer;
-import sun.hotspot.WhiteBox;
-import static jdk.test.lib.Asserts.*;
-
-public class ImageReadTest implements LocationConstants {
-
- public static final WhiteBox wb = WhiteBox.getWhiteBox();
-
- public static void main(String... args) throws Exception {
- String javaHome = System.getProperty("java.home");
- String imageFile = javaHome + File.separator + "lib"
- + File.separator + "modules" + File.separator
- + "bootmodules.jimage";
-
- if (!(new File(imageFile)).exists()) {
- System.out.printf("Test skipped.");
- return;
- }
-
- boolean isMMap = args[0].equals("+");
-
- long id = wb.imageOpenImage(imageFile, isMMap);
-
- final String mm = isMMap ? "-XX:+MemoryMapImage" : "-XX:-MemoryMapImage";
- final int magic = 0xCAFEBABE;
-
- String className = "/java.base/java/lang/String.class";
- long[] offsetArr = wb.imageFindAttributes(id, className.getBytes());
- long offset = offsetArr[LOCATION_ATTRIBUTE_OFFSET];
- long size = offsetArr[LOCATION_ATTRIBUTE_UNCOMPRESSED];
-
- // positive: read
- ByteBuffer buf = ByteBuffer.allocateDirect((int) size);
- assertTrue(wb.imageRead(id, offset, buf, size), "Failed. Read operation returned false, should be true");
- int m = buf.getInt();
- assertTrue(m == magic, "Failed. Read operation returned true but wrong magic = " + magic);
-
- // positive: mmap
- if (isMMap) {
- long dataAddr = wb.imageGetDataAddress(id);
- assertFalse(dataAddr == 0L, "Failed. Did not obtain data address on mmapped test");
- int data = wb.imageGetIntAtAddress(dataAddr, (int) offset, true);
- assertTrue(data == magic, "Failed. MMap operation returned true but wrong magic = " + data);
- }
-
- // negative: wrong offset
- boolean success = wb.imageRead(id, -100, buf, size);
- assertFalse(success, "Failed. Read operation (wrong offset): returned true");
-
- // negative: too big offset
- long filesize = new File(imageFile).length();
- success = wb.imageRead(id, filesize + 1, buf, size);
- assertFalse(success, "Failed. Read operation (offset > file size) returned true");
-
- // negative: negative size
- success = wb.imageRead(id, offset, buf, -100);
- assertFalse(success, "Failed. Read operation (negative size) returned true");
-
- wb.imageCloseImage(id);
- }
-}
--- a/hotspot/test/runtime/modules/ImageFile/LocationConstants.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-public interface LocationConstants {
- // keep this in sync with enum in ImageLocation C++ class in the
- // hotspot's C++ header file imageFile.hpp
- public static final int LOCATION_ATTRIBUTE_END = 0; // End of attribute stream marker
- public static final int LOCATION_ATTRIBUTE_MODULE = 1; // String table offset of module name
- public static final int LOCATION_ATTRIBUTE_PARENT = 2; // String table offset of resource path parent
- public static final int LOCATION_ATTRIBUTE_BASE = 3; // String table offset of resource path base
- public static final int LOCATION_ATTRIBUTE_EXTENSION = 4; // String table offset of resource path extension
- public static final int LOCATION_ATTRIBUTE_OFFSET = 5; // Container byte offset of resource
- public static final int LOCATION_ATTRIBUTE_COMPRESSED = 6; // In image byte size of the compressed resource
- public static final int LOCATION_ATTRIBUTE_UNCOMPRESSED = 7; // In memory byte size of the uncompressed resource
- public static final int LOCATION_ATTRIBUTE_COUNT = 8; // Number of attribute kinds
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jdk/test/lib/AllocationHelper.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,116 @@
+/*
+* Copyright (c) 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 jdk.test.lib;
+
+import java.util.LinkedList;
+import java.util.concurrent.Callable;
+
+/**
+ * Helper class which allocates memory.
+ *
+ * Typical usage:
+ * <pre>
+ * {@code
+ * AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE,
+ * () -> (verifier()));
+ * // Allocate byte[CHUNK_SIZE] ARRAY_LENGTH times. Total allocated bytes will be CHUNK_SIZE * ARRAY_LENGTH + refs length.
+ * // Then invoke verifier and iterate MAX_ITERATIONS times.
+ * allocator.allocateMemoryAndVerify();
+ * }
+ * </pre>
+ */
+public final class AllocationHelper {
+
+ private final int arrayLength;
+ private final int maxIterations;
+ private final int chunkSize;
+
+ // garbageStorage is used to store link to garbage to prevent optimization.
+ private static Object garbageStorage;
+ private byte garbage[][];
+ private final Callable<?> verifierInstance;
+
+ /**
+ * Create an AllocationHelper with specified iteration count, array length, chunk size and verifier.
+ *
+ * @param maxIterations
+ * @param arrayLength
+ * @param chunkSize
+ * @param verifier - Callable instance which will be invoked after all allocation cycle. Can be null;
+ */
+ public AllocationHelper(int maxIterations, int arrayLength, int chunkSize, Callable<?> verifier) {
+ if ((arrayLength <= 0) || (maxIterations <= 0) || (chunkSize <= 0)) {
+ throw new IllegalArgumentException("maxIterations, arrayLength and chunkSize should be greater then 0.");
+ }
+ this.arrayLength = arrayLength;
+ this.maxIterations = maxIterations;
+ this.chunkSize = chunkSize;
+ verifierInstance = verifier;
+ garbage = new byte[this.arrayLength][];
+ garbageStorage = garbage;
+ }
+
+ private void allocateMemoryOneIteration() {
+ for (int j = 0; j < arrayLength; j++) {
+ garbage[j] = new byte[chunkSize];
+ }
+ }
+
+ /**
+ * Allocate memory and invoke Verifier during all iteration.
+ *
+ * @throws java.lang.Exception
+ */
+ public void allocateMemoryAndVerify() throws Exception {
+ for (int i = 0; i < maxIterations; i++) {
+ allocateMemoryOneIteration();
+ if (verifierInstance != null) {
+ verifierInstance.call();
+ }
+ }
+ }
+
+ /**
+ * The same as allocateMemoryAndVerify() but hides OOME
+ *
+ * @throws Exception
+ */
+ public void allocateMemoryAndVerifyNoOOME() throws Exception {
+ try {
+ allocateMemoryAndVerify();
+ } catch (OutOfMemoryError e) {
+ // exit on OOME
+ }
+ }
+
+ /**
+ * Release link to allocated garbage to make it available for further GC
+ */
+ public void release() {
+ if (garbage != null) {
+ garbage = null;
+ garbageStorage = null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jdk/test/lib/HeapRegionUsageTool.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,107 @@
+/*
+* Copyright (c) 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 jdk.test.lib;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.MemoryUsage;
+
+/**
+ * Utility class used by tests to get heap region usage.
+ */
+public final class HeapRegionUsageTool {
+
+ /**
+ * Get MemoryUsage from MemoryPoolMXBean which name matches passed string.
+ *
+ * @param name
+ * @return MemoryUsage
+ */
+ private static MemoryUsage getUsage(String name){
+ for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
+ if (pool.getName().matches(name)) {
+ return pool.getUsage();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get MemoryUsage of Eden space.
+ *
+ * @return MemoryUsage
+ */
+ public static MemoryUsage getEdenUsage() {
+ return getUsage(".*Eden.*");
+ }
+
+ /**
+ * Get MemoryUsage of Survivor space.
+ *
+ * @return MemoryUsage
+ */
+ public static MemoryUsage getSurvivorUsage() {
+ return getUsage(".*Survivor.*");
+ }
+
+ /**
+ * Get memory usage of Tenured space
+ *
+ * @return MemoryUsage
+ */
+ public static MemoryUsage getOldUsage() {
+ return getUsage(".*(Old|Tenured).*");
+ }
+
+ /**
+ * Get heap usage.
+ *
+ * @return MemoryUsage
+ */
+ public static MemoryUsage getHeapUsage() {
+ return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+ }
+
+ /**
+ * Helper function to align up.
+ *
+ * @param value
+ * @param alignment
+ * @return aligned value
+ */
+ public static long alignUp(long value, long alignment) {
+ return (value + alignment - 1) & ~(alignment - 1);
+ }
+
+ /**
+ * Helper function to align down.
+ *
+ * @param value
+ * @param alignment
+ * @return aligned value
+ */
+ public static long alignDown(long value, long alignment) {
+ return value & ~(alignment - 1);
+ }
+}
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java Mon Sep 14 07:02:50 2015 +0200
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java Mon Sep 14 07:03:04 2015 +0000
@@ -428,4 +428,28 @@
public static long adjustTimeout(long tOut) {
return Math.round(tOut * Utils.TIMEOUT_FACTOR);
}
+
+ /**
+ * Runs runnable and checks that it throws expected exception. If exceptionException is null it means
+ * that we expect no exception to be thrown.
+ * @param runnable what we run
+ * @param expectedException expected exception
+ */
+ public static void runAndCheckException(Runnable runnable, Class<? extends Throwable> expectedException) {
+ try {
+ runnable.run();
+ if (expectedException != null) {
+ throw new AssertionError("Didn't get expected exception " + expectedException.getSimpleName());
+ }
+ } catch (Throwable t) {
+ if (expectedException == null) {
+ throw new AssertionError("Got unexpected exception ", t);
+ }
+ if (!expectedException.isAssignableFrom(t.getClass())) {
+ throw new AssertionError(String.format("Got unexpected exception %s instead of %s",
+ t.getClass().getSimpleName(), expectedException.getSimpleName()), t);
+ }
+ }
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary_tests/whitebox/BlobSanityTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test BlobSanityTest
+ * @bug 8132980
+ * @library /testlibrary /../../test/lib
+ * @modules java.management/sun.management
+ * @build BlobSanityTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI BlobSanityTest
+ * @summary sanity testing of allocateCodeBlob, freeCodeBlob and getCodeBlob
+ */
+
+
+import sun.hotspot.WhiteBox;
+
+import java.util.function.Consumer;
+import jdk.test.lib.Utils;
+
+public class BlobSanityTest {
+
+ private static void runTest(Consumer<Integer> consumer, int val, String testCaseName, Class<? extends Throwable>
+ expectedException) {
+ System.out.println("Calling " + testCaseName);
+ Utils.runAndCheckException(() -> consumer.accept(val), expectedException);
+ System.out.println("Looks ok");
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Crash means that sanity check failed");
+
+ WhiteBox wb = WhiteBox.getWhiteBox();
+
+ runTest(wb::freeCodeBlob, 0, "wb::freeCodeBlob(0)", null);
+ runTest(wb::getCodeBlob, 0, "wb::getCodeBlob(0)", NullPointerException.class);
+ runTest(x -> wb.allocateCodeBlob(x, 0), -1, "wb::allocateCodeBlob(-1,0)", IllegalArgumentException.class);
+ }
+}
--- a/jaxp/.hgtags Mon Sep 14 07:02:50 2015 +0200
+++ b/jaxp/.hgtags Mon Sep 14 07:03:04 2015 +0000
@@ -322,3 +322,4 @@
be357705874c4ba1a69c38fb211e5e31e35bf9cb jdk9-b77
5b1899c9822db4a80a29cac82af492afea9f8f41 jdk9-b78
cf809edc840ff7546677d38b13ebd8b3cae2bbda jdk9-b79
+f464f9b2fb1178f6a957e5730b4b5252c6149ed9 jdk9-b80
--- a/jaxws/.hgtags Mon Sep 14 07:02:50 2015 +0200
+++ b/jaxws/.hgtags Mon Sep 14 07:03:04 2015 +0000
@@ -325,3 +325,4 @@
bd6ece68cf8aca34c8d992569892060c82cfd3f1 jdk9-b77
ac1748bab0743137574be3451307b6a6361719eb jdk9-b78
42ae657e0e104fa7877996b8095f2e3ab1596118 jdk9-b79
+e9940bf1c8ddaa6f1f5f1813846b080f0ccaf50b jdk9-b80
--- a/jdk/.hgtags Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/.hgtags Mon Sep 14 07:03:04 2015 +0000
@@ -322,3 +322,4 @@
7fd081100f48828431e7c1bff65c906ee759069b jdk9-b77
0940ce86c614458f5bdd72278b190abbf36b7b45 jdk9-b78
d99c2ffdd0f15753e69126583688f2f075a0a5e8 jdk9-b79
+4947810137ae53abba3028cc366af953d90fa81a jdk9-b80
--- a/jdk/README Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/README Mon Sep 14 07:03:04 2015 +0000
@@ -25,5 +25,3 @@
5. Construct the images:
cd make && gnumake images
The resulting JDK image should be found in build/*/j2sdk-image
-
-
--- a/jdk/make/lib/Awt2dLibraries.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/make/lib/Awt2dLibraries.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -887,7 +887,8 @@
$(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS), \
DISABLED_WARNINGS_gcc := sign-compare type-limits unused-result maybe-uninitialized, \
DISABLED_WARNINGS_clang := incompatible-pointer-types, \
- DISABLED_WARNINGS_solstudio := E_NEWLINE_NOT_LAST E_DECLARATION_IN_CODE, \
+ DISABLED_WARNINGS_solstudio := E_NEWLINE_NOT_LAST E_DECLARATION_IN_CODE \
+ E_STATEMENT_NOT_REACHED, \
DISABLED_WARNINGS_microsoft := 4018 4244 4267, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libsplashscreen/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
--- a/jdk/make/lib/CoreLibraries.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/make/lib/CoreLibraries.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -146,6 +146,7 @@
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJAVA_CFLAGS), \
+ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
@@ -307,7 +308,9 @@
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
OPTIMIZATION := HIGH, \
CFLAGS := $(LIBJLI_CFLAGS), \
- DISABLED_WARNINGS_solstudio := E_ASM_DISABLES_OPTIMIZATION, \
+ DISABLED_WARNINGS_solstudio := \
+ E_ASM_DISABLES_OPTIMIZATION \
+ E_STATEMENT_NOT_REACHED, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjli/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/jdk/make/lib/NetworkingLibraries.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/make/lib/NetworkingLibraries.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -35,6 +35,7 @@
DISABLED_WARNINGS_gcc := format-nonliteral, \
DISABLED_WARNINGS_clang := parentheses-equality constant-logical-operand, \
DISABLED_WARNINGS_microsoft := 4244 4047 4133 4996, \
+ DISABLED_WARNINGS_solstudio := E_ARG_INCOMPATIBLE_WITH_ARG_L, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libnet/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/jdk/make/lib/NioLibraries.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/make/lib/NioLibraries.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -47,7 +47,7 @@
ifeq ($(OPENJDK_TARGET_OS), macosx)
BUILD_LIBNIO_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libnio/mapfile-$(OPENJDK_TARGET_OS)
BUILD_LIBNIO_EXFILES += \
- GnomeFileTypeDetector.c \
+ GioFileTypeDetector.c \
#
endif
--- a/jdk/make/mapfiles/libnio/mapfile-linux Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/make/mapfiles/libnio/mapfile-linux Mon Sep 14 07:03:04 2015 +0000
@@ -135,8 +135,8 @@
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
- Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio;
- Java_sun_nio_fs_GnomeFileTypeDetector_probeGio;
+ Java_sun_nio_fs_GioFileTypeDetector_initializeGio;
+ Java_sun_nio_fs_GioFileTypeDetector_probeGio;
Java_sun_nio_fs_MagicFileTypeDetector_initialize0;
Java_sun_nio_fs_MagicFileTypeDetector_probe0;
Java_sun_nio_fs_LinuxWatchService_eventSize;
--- a/jdk/make/mapfiles/libnio/mapfile-solaris Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/make/mapfiles/libnio/mapfile-solaris Mon Sep 14 07:03:04 2015 +0000
@@ -130,8 +130,8 @@
Java_sun_nio_ch_SolarisEventPort_port_1get;
Java_sun_nio_ch_SolarisEventPort_port_1getn;
Java_sun_nio_ch_SolarisEventPort_port_1send;
- Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio;
- Java_sun_nio_fs_GnomeFileTypeDetector_probeGio;
+ Java_sun_nio_fs_GioFileTypeDetector_initializeGio;
+ Java_sun_nio_fs_GioFileTypeDetector_probeGio;
Java_sun_nio_fs_UnixNativeDispatcher_init;
Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
Java_sun_nio_fs_UnixNativeDispatcher_strerror;
--- a/jdk/make/netbeans/jdbc/build.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/make/netbeans/jdbc/build.properties Mon Sep 14 07:03:04 2015 +0000
@@ -43,4 +43,4 @@
build.number = b00
jdbc.version = ${build.release}-${user.name}-${build.number}
jdbc.args = -debug
-javadoc.options=-J-Xmx256m -Xdoclint:none -keywords -quiet
\ No newline at end of file
+javadoc.options=-J-Xmx256m -Xdoclint:none -keywords -quiet
--- a/jdk/src/demo/share/applets/Fractal/example1.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/demo/share/applets/Fractal/example1.html Mon Sep 14 07:03:04 2015 +0000
@@ -23,5 +23,3 @@
<a href="CLSFractal.java">The source</a>.
</body>
</html>
-
-
--- a/jdk/src/demo/share/applets/MoleculeViewer/example1.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/demo/share/applets/MoleculeViewer/example1.html Mon Sep 14 07:03:04 2015 +0000
@@ -14,9 +14,3 @@
<a href="XYZApp.java">The source</a>.
</body>
</html>
-
-
-
-
-
-
--- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -106,7 +106,7 @@
new GetPropertyAction("user.home")), ".mime.types");
Path etcMimeTypes = Paths.get("/etc/mime.types");
- return chain(new GnomeFileTypeDetector(),
+ return chain(new GioFileTypeDetector(),
new MimeTypesFileTypeDetector(userMimeTypes),
new MimeTypesFileTypeDetector(etcMimeTypes),
new MagicFileTypeDetector());
--- a/jdk/src/java.base/share/classes/java/security/KeyStore.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.base/share/classes/java/security/KeyStore.java Mon Sep 14 07:03:04 2015 +0000
@@ -1611,8 +1611,13 @@
* First the keystore type is determined by probing the specified file.
* Then a keystore object is instantiated and loaded using the data from
* that file.
- * A password may be supplied to unlock the keystore data or perform an
- * integrity check.
+ *
+ * <p>
+ * A password may be given to unlock the keystore
+ * (e.g. the keystore resides on a hardware token device),
+ * or to check the integrity of the keystore data.
+ * If a password is not given for integrity checking,
+ * then integrity checking is not performed.
*
* <p>
* This method traverses the list of registered security
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Mon Sep 14 07:03:04 2015 +0000
@@ -60,8 +60,8 @@
\ -dsa | -disablesystemassertions\n\
\ disable system assertions\n\
\ -agentlib:<libname>[=<options>]\n\
-\ load native agent library <libname>, e.g. -agentlib:hprof\n\
-\ see also, -agentlib:jdwp=help and -agentlib:hprof=help\n\
+\ load native agent library <libname>, e.g. -agentlib:jdwp\n\
+\ see also -agentlib:jdwp=help\n\
\ -agentpath:<pathname>[=<options>]\n\
\ load native agent library by full pathname\n\
\ -javaagent:<jarpath>[=<options>]\n\
--- a/jdk/src/java.base/share/native/libzip/Adler32.c Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.base/share/native/libzip/Adler32.c Mon Sep 14 07:03:04 2015 +0000
@@ -66,5 +66,3 @@
}
return adler;
}
-
-
--- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -89,7 +89,7 @@
new GetPropertyAction("user.home")), ".mime.types");
Path etcMimeTypes = Paths.get("/etc/mime.types");
- return chain(new GnomeFileTypeDetector(),
+ return chain(new GioFileTypeDetector(),
new MimeTypesFileTypeDetector(userMimeTypes),
new MimeTypesFileTypeDetector(etcMimeTypes));
}
--- a/jdk/src/java.base/unix/classes/sun/net/www/content-types.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.base/unix/classes/sun/net/www/content-types.properties Mon Sep 14 07:03:04 2015 +0000
@@ -275,6 +275,3 @@
application/xml: \
description=XML document;\
file_extensions=.xml
-
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/GioFileTypeDetector.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2008, 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.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.Path;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * File type detector that uses the GNOME I/O library to guess the
+ * MIME type of a file.
+ */
+
+public class GioFileTypeDetector
+ extends AbstractFileTypeDetector
+{
+ // true if GIO is available
+ private final boolean gioAvailable;
+
+ public GioFileTypeDetector() {
+ gioAvailable = initializeGio();
+ }
+
+ @Override
+ public String implProbeContentType(Path obj) throws IOException {
+ if (!gioAvailable)
+ return null;
+ if (!(obj instanceof UnixPath))
+ return null;
+
+ UnixPath path = (UnixPath)obj;
+ NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls());
+ try {
+ // GIO may access file so need permission check
+ path.checkRead();
+ byte[] type = probeGio(buffer.address());
+ return (type == null) ? null : Util.toString(type);
+ } finally {
+ buffer.release();
+ }
+
+ }
+
+ // GIO
+ private static native boolean initializeGio();
+ //
+ // The probeGIO() method is synchronized to avert potential problems
+ // such as crashes due to a suspected lack of thread safety in GIO.
+ //
+ private static synchronized native byte[] probeGio(long pathAddress);
+
+ static {
+ AccessController.doPrivileged(new PrivilegedAction<>() {
+ public Void run() {
+ System.loadLibrary("nio");
+ return null;
+ }});
+ }
+}
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/GnomeFileTypeDetector.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2008, 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.
- */
-
-package sun.nio.fs;
-
-import java.nio.file.Path;
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * File type detector that uses the GNOME I/O library to guess the
- * MIME type of a file.
- */
-
-public class GnomeFileTypeDetector
- extends AbstractFileTypeDetector
-{
- // true if GIO is available
- private final boolean gioAvailable;
-
- public GnomeFileTypeDetector() {
- gioAvailable = initializeGio();
- }
-
- @Override
- public String implProbeContentType(Path obj) throws IOException {
- if (!gioAvailable)
- return null;
- if (!(obj instanceof UnixPath))
- return null;
-
- UnixPath path = (UnixPath)obj;
- NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls());
- try {
- // GIO may access file so need permission check
- path.checkRead();
- byte[] type = probeGio(buffer.address());
- return (type == null) ? null : Util.toString(type);
- } finally {
- buffer.release();
- }
-
- }
-
- // GIO
- private static native boolean initializeGio();
- private static synchronized native byte[] probeGio(long pathAddress);
-
- static {
- AccessController.doPrivileged(new PrivilegedAction<>() {
- public Void run() {
- System.loadLibrary("nio");
- return null;
- }});
- }
-}
--- a/jdk/src/java.base/unix/native/libjava/FileDescriptor_md.c Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.base/unix/native/libjava/FileDescriptor_md.c Mon Sep 14 07:03:04 2015 +0000
@@ -26,9 +26,11 @@
#include <unistd.h>
#include <fcntl.h>
+#include "jni.h"
+#include "jni_util.h"
#include "jvm.h"
+
#include "io_util_md.h"
-
#include "java_io_FileDescriptor.h"
/*******************************************************************/
@@ -47,8 +49,8 @@
JNIEXPORT void JNICALL
Java_java_io_FileDescriptor_initIDs(JNIEnv *env, jclass fdClass) {
- IO_fd_fdID = (*env)->GetFieldID(env, fdClass, "fd", "I");
- IO_append_fdID = (*env)->GetFieldID(env, fdClass, "append", "Z");
+ CHECK_NULL(IO_fd_fdID = (*env)->GetFieldID(env, fdClass, "fd", "I"));
+ CHECK_NULL(IO_append_fdID = (*env)->GetFieldID(env, fdClass, "append", "Z"));
}
/**************************************************************
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/native/libnio/fs/GioFileTypeDetector.c Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2008, 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.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#ifdef __solaris__
+#include <strings.h>
+#endif
+
+#if defined(__linux__)
+#include <string.h>
+#endif
+
+/*
+ * For reference see for example the GFileInfo section at
+ * https://developer.gnome.org/gio/unstable/.
+ */
+
+/* Definitions for GIO */
+
+#define G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "standard::content-type"
+
+typedef void* gpointer;
+typedef struct _GFile GFile;
+typedef struct _GFileInfo GFileInfo;
+typedef struct _GCancellable GCancellable;
+typedef struct _GError GError;
+
+typedef enum {
+ G_FILE_QUERY_INFO_NONE = 0
+} GFileQueryInfoFlags;
+
+typedef void (*g_type_init_func)(void);
+typedef void (*g_object_unref_func)(gpointer object);
+typedef GFile* (*g_file_new_for_path_func)(const char* path);
+typedef GFileInfo* (*g_file_query_info_func)(GFile *file,
+ const char *attributes, GFileQueryInfoFlags flags,
+ GCancellable *cancellable, GError **error);
+typedef char* (*g_file_info_get_content_type_func)(GFileInfo *info);
+
+static g_type_init_func g_type_init;
+static g_object_unref_func g_object_unref;
+static g_file_new_for_path_func g_file_new_for_path;
+static g_file_query_info_func g_file_query_info;
+static g_file_info_get_content_type_func g_file_info_get_content_type;
+
+
+#include "sun_nio_fs_GioFileTypeDetector.h"
+
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_fs_GioFileTypeDetector_initializeGio
+ (JNIEnv* env, jclass this)
+{
+ void* gio_handle;
+
+ gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY);
+ if (gio_handle == NULL) {
+ gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY);
+ if (gio_handle == NULL) {
+ return JNI_FALSE;
+ }
+ }
+
+ g_type_init = (g_type_init_func)dlsym(gio_handle, "g_type_init");
+ (*g_type_init)();
+
+ g_object_unref = (g_object_unref_func)dlsym(gio_handle, "g_object_unref");
+
+ g_file_new_for_path =
+ (g_file_new_for_path_func)dlsym(gio_handle, "g_file_new_for_path");
+
+ g_file_query_info =
+ (g_file_query_info_func)dlsym(gio_handle, "g_file_query_info");
+
+ g_file_info_get_content_type = (g_file_info_get_content_type_func)
+ dlsym(gio_handle, "g_file_info_get_content_type");
+
+
+ if (g_type_init == NULL ||
+ g_object_unref == NULL ||
+ g_file_new_for_path == NULL ||
+ g_file_query_info == NULL ||
+ g_file_info_get_content_type == NULL)
+ {
+ dlclose(gio_handle);
+ return JNI_FALSE;
+ }
+
+ (*g_type_init)();
+ return JNI_TRUE;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_GioFileTypeDetector_probeGio
+ (JNIEnv* env, jclass this, jlong pathAddress)
+{
+ char* path = (char*)jlong_to_ptr(pathAddress);
+ GFile* gfile;
+ GFileInfo* gfileinfo;
+ jbyteArray result = NULL;
+
+ gfile = (*g_file_new_for_path)(path);
+ gfileinfo = (*g_file_query_info)(gfile, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ if (gfileinfo != NULL) {
+ const char* mime = (*g_file_info_get_content_type)(gfileinfo);
+ if (mime != NULL) {
+ jsize len = strlen(mime);
+ result = (*env)->NewByteArray(env, len);
+ if (result != NULL) {
+ (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime);
+ }
+ }
+ (*g_object_unref)(gfileinfo);
+ }
+ (*g_object_unref)(gfile);
+
+ return result;
+}
--- a/jdk/src/java.base/unix/native/libnio/fs/GnomeFileTypeDetector.c Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2008, 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.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-
-#include <stdlib.h>
-#include <dlfcn.h>
-
-#ifdef __solaris__
-#include <strings.h>
-#endif
-
-#if defined(__linux__)
-#include <string.h>
-#endif
-
-/*
- * For reference see for example the GFileInfo section at
- * https://developer.gnome.org/gio/unstable/.
- */
-
-/* Definitions for GIO */
-
-#define G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "standard::content-type"
-
-typedef void* gpointer;
-typedef struct _GFile GFile;
-typedef struct _GFileInfo GFileInfo;
-typedef struct _GCancellable GCancellable;
-typedef struct _GError GError;
-
-typedef enum {
- G_FILE_QUERY_INFO_NONE = 0
-} GFileQueryInfoFlags;
-
-typedef void (*g_type_init_func)(void);
-typedef void (*g_object_unref_func)(gpointer object);
-typedef GFile* (*g_file_new_for_path_func)(const char* path);
-typedef GFileInfo* (*g_file_query_info_func)(GFile *file,
- const char *attributes, GFileQueryInfoFlags flags,
- GCancellable *cancellable, GError **error);
-typedef char* (*g_file_info_get_content_type_func)(GFileInfo *info);
-
-static g_type_init_func g_type_init;
-static g_object_unref_func g_object_unref;
-static g_file_new_for_path_func g_file_new_for_path;
-static g_file_query_info_func g_file_query_info;
-static g_file_info_get_content_type_func g_file_info_get_content_type;
-
-
-#include "sun_nio_fs_GnomeFileTypeDetector.h"
-
-
-JNIEXPORT jboolean JNICALL
-Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio
- (JNIEnv* env, jclass this)
-{
- void* gio_handle;
-
- gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY);
- if (gio_handle == NULL) {
- gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY);
- if (gio_handle == NULL) {
- return JNI_FALSE;
- }
- }
-
- g_type_init = (g_type_init_func)dlsym(gio_handle, "g_type_init");
- (*g_type_init)();
-
- g_object_unref = (g_object_unref_func)dlsym(gio_handle, "g_object_unref");
-
- g_file_new_for_path =
- (g_file_new_for_path_func)dlsym(gio_handle, "g_file_new_for_path");
-
- g_file_query_info =
- (g_file_query_info_func)dlsym(gio_handle, "g_file_query_info");
-
- g_file_info_get_content_type = (g_file_info_get_content_type_func)
- dlsym(gio_handle, "g_file_info_get_content_type");
-
-
- if (g_type_init == NULL ||
- g_object_unref == NULL ||
- g_file_new_for_path == NULL ||
- g_file_query_info == NULL ||
- g_file_info_get_content_type == NULL)
- {
- dlclose(gio_handle);
- return JNI_FALSE;
- }
-
- (*g_type_init)();
- return JNI_TRUE;
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_sun_nio_fs_GnomeFileTypeDetector_probeGio
- (JNIEnv* env, jclass this, jlong pathAddress)
-{
- char* path = (char*)jlong_to_ptr(pathAddress);
- GFile* gfile;
- GFileInfo* gfileinfo;
- jbyteArray result = NULL;
-
- gfile = (*g_file_new_for_path)(path);
- gfileinfo = (*g_file_query_info)(gfile, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
- G_FILE_QUERY_INFO_NONE, NULL, NULL);
- if (gfileinfo != NULL) {
- const char* mime = (*g_file_info_get_content_type)(gfileinfo);
- if (mime != NULL) {
- jsize len = strlen(mime);
- result = (*env)->NewByteArray(env, len);
- if (result != NULL) {
- (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime);
- }
- }
- (*g_object_unref)(gfileinfo);
- }
- (*g_object_unref)(gfile);
-
- return result;
-}
--- a/jdk/src/java.base/windows/classes/sun/net/www/content-types.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.base/windows/classes/sun/net/www/content-types.properties Mon Sep 14 07:03:04 2015 +0000
@@ -272,5 +272,3 @@
application/xml: \
description=XML document;\
file_extensions=.xml
-
-
--- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_OpenAppHandler.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_OpenAppHandler.java Mon Sep 14 07:03:04 2015 +0000
@@ -27,4 +27,4 @@
interface _OpenAppHandler {
void handleOpenApp();
-}
\ No newline at end of file
+}
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java Mon Sep 14 07:03:04 2015 +0000
@@ -1098,4 +1098,4 @@
};
table.putDefaults(uiDefaults);
}
-}
\ No newline at end of file
+}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDataTransferer.java Mon Sep 14 07:03:04 2015 +0000
@@ -278,5 +278,3 @@
return false;
}
}
-
-
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Mon Sep 14 07:03:04 2015 +0000
@@ -1406,5 +1406,3 @@
return underMouse;
}
-
-
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m Mon Sep 14 07:03:04 2015 +0000
@@ -289,4 +289,4 @@
JNF_COCOA_EXIT(env);
return ret;
-}
\ No newline at end of file
+}
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/MultiResolutionCachedImage.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/MultiResolutionCachedImage.java Mon Sep 14 07:03:04 2015 +0000
@@ -183,4 +183,4 @@
return false;
}
}
-}
\ No newline at end of file
+}
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/AnchorTables.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/AnchorTables.h Mon Sep 14 07:03:04 2015 +0000
@@ -80,5 +80,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/CharSubstitutionFilter.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/CharSubstitutionFilter.h Mon Sep 14 07:03:04 2015 +0000
@@ -104,5 +104,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/CursiveAttachmentSubtables.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/CursiveAttachmentSubtables.h Mon Sep 14 07:03:04 2015 +0000
@@ -63,5 +63,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.h Mon Sep 14 07:03:04 2015 +0000
@@ -61,5 +61,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/MPreFixups.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/MPreFixups.h Mon Sep 14 07:03:04 2015 +0000
@@ -63,5 +63,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/MarkArrays.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/MarkArrays.h Mon Sep 14 07:03:04 2015 +0000
@@ -62,5 +62,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/PairPositioningSubtables.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/PairPositioningSubtables.h Mon Sep 14 07:03:04 2015 +0000
@@ -109,5 +109,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/SinglePositioningSubtables.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/SinglePositioningSubtables.h Mon Sep 14 07:03:04 2015 +0000
@@ -71,5 +71,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/SingleSubstitutionSubtables.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/SingleSubstitutionSubtables.h Mon Sep 14 07:03:04 2015 +0000
@@ -68,5 +68,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ThaiShaping.h Mon Sep 14 07:03:04 2015 +0000
@@ -129,5 +129,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ValueRecords.h Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ValueRecords.h Mon Sep 14 07:03:04 2015 +0000
@@ -94,5 +94,3 @@
U_NAMESPACE_END
#endif
-
-
--- a/jdk/src/java.desktop/share/native/liblcms/cmslut.c Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/liblcms/cmslut.c Mon Sep 14 07:03:04 2015 +0000
@@ -1836,5 +1836,3 @@
return TRUE;
}
-
-
--- a/jdk/src/java.desktop/share/native/liblcms/cmsmtrx.c Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsmtrx.c Mon Sep 14 07:03:04 2015 +0000
@@ -201,5 +201,3 @@
r->n[VY] = a->v[1].n[VX]*v->n[VX] + a->v[1].n[VY]*v->n[VY] + a->v[1].n[VZ]*v->n[VZ];
r->n[VZ] = a->v[2].n[VX]*v->n[VX] + a->v[2].n[VY]*v->n[VY] + a->v[2].n[VZ]*v->n[VZ];
}
-
-
--- a/jdk/src/java.desktop/share/native/liblcms/cmsplugin.c Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/liblcms/cmsplugin.c Mon Sep 14 07:03:04 2015 +0000
@@ -989,5 +989,3 @@
{
return _cmsContextGetClientChunk(ContextID, UserPtr);
}
-
-
--- a/jdk/src/java.desktop/share/native/liblcms/cmswtpnt.c Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/liblcms/cmswtpnt.c Mon Sep 14 07:03:04 2015 +0000
@@ -376,5 +376,3 @@
return TRUE;
}
-
-
--- a/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c Mon Sep 14 07:03:04 2015 +0000
@@ -234,4 +234,4 @@
return 1;
}
return splash->scaleFactor;
-}
\ No newline at end of file
+}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/DllUtil.cpp Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/DllUtil.cpp Mon Sep 14 07:03:04 2015 +0000
@@ -84,5 +84,3 @@
}
throw FunctionUnavailableException();
}
-
-
--- a/jdk/src/java.desktop/windows/native/libawt/windows/README.JNI Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/README.JNI Mon Sep 14 07:03:04 2015 +0000
@@ -131,5 +131,3 @@
2. Handle exceptions properly. The current code lacks error checking
and recovery. This leads to random runtime crashes.
-
-
--- a/jdk/src/java.logging/share/classes/java/util/logging/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.logging/share/classes/java/util/logging/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -126,8 +126,3 @@
</body>
</html>
-
-
-
-
-
--- a/jdk/src/java.management/share/classes/javax/management/ObjectName.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.management/share/classes/javax/management/ObjectName.java Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -218,9 +218,19 @@
* <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>.
*
* @since 1.5
+ *
+ * @implNote The maximum allowed length of the domain name in this implementation
+ * is {@code Integer.MAX_VALUE/4}
*/
@SuppressWarnings("serial") // don't complain serialVersionUID not constant
public class ObjectName implements Comparable<ObjectName>, QueryExp {
+ private static final int DOMAIN_PATTERN = 0x8000_0000;
+ private static final int PROPLIST_PATTERN = 0x4000_0000;
+ private static final int PROPVAL_PATTERN = 0x2000_0000;
+
+ private static final int FLAG_MASK = DOMAIN_PATTERN | PROPLIST_PATTERN |
+ PROPVAL_PATTERN;
+ private static final int DOMAIN_LENGTH_MASK = ~FLAG_MASK;
/**
* A structure recording property structure and
@@ -365,33 +375,25 @@
/**
- * The length of the domain part of built objectname
- */
- private transient int _domain_length = 0;
-
-
- /**
* The propertyList of built object name. Initialized lazily.
* Table that contains all the pairs (key,value) for this ObjectName.
*/
private transient Map<String,String> _propertyList;
/**
- * boolean that declares if this ObjectName domain part is a pattern
- */
- private transient boolean _domain_pattern = false;
-
- /**
- * boolean that declares if this ObjectName contains a pattern on the
- * key property list
+ * This field encodes _domain_pattern, _property_list_pattern and
+ * _property_value_pattern booleans and _domain_length integer.
+ * <p>
+ * The following masks can be used to extract the value:
+ * <ul>
+ * <li>{@linkplain ObjectName#DOMAIN_PATTERN}</li>
+ * <li>{@linkplain ObjectName#PROPLIST_PATTERN}</li>
+ * <li>{@linkplain ObjectName#PROPVAL_PATTERN}</li>
+ * <li>{@linkplain ObjectName#DOMAIN_LENGTH_MASK}</li>
+ * </ul>
+ * </p>.
*/
- private transient boolean _property_list_pattern = false;
-
- /**
- * boolean that declares if this ObjectName contains a pattern on the
- * value of at least one key property
- */
- private transient boolean _property_value_pattern = false;
+ private transient int _compressed_storage = 0x0;
// Instance private fields <=======================================
@@ -426,11 +428,11 @@
_canonicalName = "*:*";
_kp_array = _Empty_property_array;
_ca_array = _Empty_property_array;
- _domain_length = 1;
+ setDomainLength(1);
_propertyList = null;
- _domain_pattern = true;
- _property_list_pattern = true;
- _property_value_pattern = false;
+ setDomainPattern(true);
+ setPropertyListPattern(true);
+ setPropertyValuePattern(false);
return;
}
@@ -448,7 +450,7 @@
while (index < len) {
switch (name_chars[index]) {
case ':' :
- _domain_length = index++;
+ setDomainLength(index++);
break domain_parsing;
case '=' :
// ":" omission check.
@@ -469,7 +471,7 @@
"Invalid character '\\n' in domain name");
case '*' :
case '?' :
- _domain_pattern = true;
+ setDomainPattern(true);
index++;
break;
default :
@@ -484,6 +486,7 @@
"Key properties cannot be empty");
// we have got the domain part, begins building of _canonicalName
+ int _domain_length = getDomainLength();
System.arraycopy(name_chars, 0, canonical_chars, 0, _domain_length);
canonical_chars[_domain_length] = ':';
cname_index = _domain_length + 1;
@@ -500,20 +503,20 @@
keys = new String[10];
_kp_array = new Property[10];
- _property_list_pattern = false;
- _property_value_pattern = false;
+ setPropertyListPattern(false);
+ setPropertyValuePattern(false);
while (index < len) {
c = name_chars[index];
// case of pattern properties
if (c == '*') {
- if (_property_list_pattern)
+ if (isPropertyListPattern())
throw new MalformedObjectNameException(
"Cannot have several '*' characters in pattern " +
"property list");
else {
- _property_list_pattern = true;
+ setPropertyListPattern(true);
if ((++index < len ) && (name_chars[index] != ','))
throw new MalformedObjectNameException(
"Invalid character found after '*': end of " +
@@ -639,7 +642,7 @@
if (!value_pattern) {
prop = new Property(key_index, key_length, value_length);
} else {
- _property_value_pattern = true;
+ setPropertyValuePattern(true);
prop = new PatternProperty(key_index, key_length, value_length);
}
key_name = name.substring(key_index, key_index + key_length);
@@ -670,7 +673,8 @@
* @exception MalformedObjectNameException The <code>domain</code>
* contains an illegal character, or one of the keys or values in
* <code>table</code> contains an illegal character, or one of the
- * values in <code>table</code> does not follow the rules for quoting.
+ * values in <code>table</code> does not follow the rules for quoting,
+ * or the domain's length exceeds the maximum allowed length.
* @exception NullPointerException One of the parameters is null.
*/
private void construct(String domain, Map<String,String> props)
@@ -696,7 +700,7 @@
// init canonicalname
final StringBuilder sb = new StringBuilder();
sb.append(domain).append(':');
- _domain_length = domain.length();
+ setDomainLength(domain.length());
// allocates the property array
int nb_props = props.size();
@@ -729,7 +733,7 @@
key.length(),
value.length());
} else {
- _property_value_pattern = true;
+ setPropertyValuePattern(true);
prop = new PatternProperty(key_index,
key.length(),
value.length());
@@ -743,10 +747,10 @@
char[] initial_chars = new char[len];
sb.getChars(0, len, initial_chars, 0);
char[] canonical_chars = new char[len];
- System.arraycopy(initial_chars, 0, canonical_chars, 0,
- _domain_length + 1);
+ int copyLen = getDomainLength() + 1;
+ System.arraycopy(initial_chars, 0, canonical_chars, 0, copyLen);
setCanonicalName(initial_chars, canonical_chars, keys, keys_map,
- _domain_length + 1, _kp_array.length);
+ copyLen, _kp_array.length);
}
// Category : Instance construction <==============================
@@ -822,7 +826,7 @@
}
// terminate canonicalname with '*' in case of pattern
- if (_property_list_pattern) {
+ if (isPropertyListPattern()) {
if (_kp_array != _Empty_property_array)
canonical_chars[prop_index++] = ',';
canonical_chars[prop_index++] = '*';
@@ -1051,13 +1055,32 @@
return false;
case '*' :
case '?' :
- _domain_pattern = true;
+ setDomainPattern(true);
break;
}
}
return true;
}
+ private int getDomainLength() {
+ return _compressed_storage & DOMAIN_LENGTH_MASK;
+ }
+
+ /**
+ * Validates and sets the domain length
+ * @param length The domain length
+ * @throws MalformedObjectNameException
+ * When the given domain length exceeds the maximum allowed length
+ */
+ private void setDomainLength(int length) throws MalformedObjectNameException {
+ if ((length & FLAG_MASK) != 0 ) {
+ throw new MalformedObjectNameException(
+ "Domain name too long. Maximum allowed domain name length is:" +
+ DOMAIN_LENGTH_MASK);
+ }
+ _compressed_storage = (_compressed_storage & FLAG_MASK) | length;
+ }
+
// Category : Internal accessors <==============================
// Category : Serialization ----------------------------------->
@@ -1225,12 +1248,12 @@
// Serializes this instance in the old serial form
// Read CR 6441274 before making any changes to this code
ObjectOutputStream.PutField fields = out.putFields();
- fields.put("domain", _canonicalName.substring(0, _domain_length));
+ fields.put("domain", _canonicalName.substring(0, getDomainLength()));
fields.put("propertyList", getKeyPropertyList());
fields.put("propertyListString", getKeyPropertyListString());
fields.put("canonicalName", _canonicalName);
- fields.put("pattern", (_domain_pattern || _property_list_pattern));
- fields.put("propertyPattern", _property_list_pattern);
+ fields.put("pattern", (_compressed_storage & (DOMAIN_PATTERN | PROPLIST_PATTERN)) != 0);
+ fields.put("propertyPattern", isPropertyListPattern());
out.writeFields();
}
else
@@ -1291,7 +1314,8 @@
* @exception MalformedObjectNameException The
* <code>domain</code>, <code>key</code>, or <code>value</code>
* contains an illegal character, or <code>value</code> does not
- * follow the rules for quoting.
+ * follow the rules for quoting, or the domain's length exceeds
+ * the maximum allowed length.
* @exception NullPointerException One of the parameters is null.
*
*/
@@ -1322,7 +1346,7 @@
* contains an illegal character, or one of the keys or values in
* <code>table</code> contains an illegal character, or one of the
* values in <code>table</code> does not follow the rules for
- * quoting.
+ * quoting, or the domain's length exceeds the maximum allowed length.
* @exception NullPointerException One of the parameters is null.
*
*/
@@ -1392,7 +1416,8 @@
* @exception MalformedObjectNameException The
* <code>domain</code>, <code>key</code>, or <code>value</code>
* contains an illegal character, or <code>value</code> does not
- * follow the rules for quoting.
+ * follow the rules for quoting, or the domain's length exceeds
+ * the maximum allowed length.
* @exception NullPointerException One of the parameters is null.
*/
public ObjectName(String domain, String key, String value)
@@ -1417,7 +1442,7 @@
* contains an illegal character, or one of the keys or values in
* <code>table</code> contains an illegal character, or one of the
* values in <code>table</code> does not follow the rules for
- * quoting.
+ * quoting, or the domain's length exceeds the maximum allowed length.
* @exception NullPointerException One of the parameters is null.
*/
public ObjectName(String domain, Hashtable<String,String> table)
@@ -1443,9 +1468,7 @@
* @return True if the name is a pattern, otherwise false.
*/
public boolean isPattern() {
- return (_domain_pattern ||
- _property_list_pattern ||
- _property_value_pattern);
+ return (_compressed_storage & FLAG_MASK) != 0;
}
/**
@@ -1455,7 +1478,20 @@
*
*/
public boolean isDomainPattern() {
- return _domain_pattern;
+ return (_compressed_storage & DOMAIN_PATTERN) != 0;
+ }
+
+ /**
+ * Marks the object name as representing a pattern on the domain part.
+ * @param value {@code true} if the domain name is a pattern,
+ * {@code false} otherwise
+ */
+ private void setDomainPattern(boolean value) {
+ if (value) {
+ _compressed_storage |= DOMAIN_PATTERN;
+ } else {
+ _compressed_storage &= ~DOMAIN_PATTERN;
+ }
}
/**
@@ -1468,7 +1504,7 @@
* @return True if the name is a property pattern, otherwise false.
*/
public boolean isPropertyPattern() {
- return _property_list_pattern || _property_value_pattern;
+ return (_compressed_storage & (PROPVAL_PATTERN | PROPLIST_PATTERN)) != 0;
}
/**
@@ -1482,7 +1518,20 @@
* @since 1.6
*/
public boolean isPropertyListPattern() {
- return _property_list_pattern;
+ return (_compressed_storage & PROPLIST_PATTERN) != 0;
+ }
+
+ /**
+ * Marks the object name as representing a pattern on the key property list.
+ * @param value {@code true} if the key property list is a pattern,
+ * {@code false} otherwise
+ */
+ private void setPropertyListPattern(boolean value) {
+ if (value) {
+ _compressed_storage |= PROPLIST_PATTERN;
+ } else {
+ _compressed_storage &= ~PROPLIST_PATTERN;
+ }
}
/**
@@ -1497,7 +1546,20 @@
* @since 1.6
*/
public boolean isPropertyValuePattern() {
- return _property_value_pattern;
+ return (_compressed_storage & PROPVAL_PATTERN) != 0;
+ }
+
+ /**
+ * Marks the object name as representing a pattern on the value part.
+ * @param value {@code true} if the value part of at least one of the
+ * key properties is a pattern, {@code false} otherwise
+ */
+ private void setPropertyValuePattern(boolean value) {
+ if (value) {
+ _compressed_storage |= PROPVAL_PATTERN;
+ } else {
+ _compressed_storage &= ~PROPVAL_PATTERN;
+ }
}
/**
@@ -1563,7 +1625,7 @@
* @return The domain.
*/
public String getDomain() {
- return _canonicalName.substring(0, _domain_length);
+ return _canonicalName.substring(0, getDomainLength());
}
/**
@@ -1640,8 +1702,8 @@
// the size of the string is the canonical one minus domain
// part and pattern part
- final int total_size = _canonicalName.length() - _domain_length - 1
- - (_property_list_pattern?2:0);
+ final int total_size = _canonicalName.length() - getDomainLength() - 1
+ - (isPropertyListPattern()?2:0);
final char[] dest_chars = new char[total_size];
final char[] value = _canonicalName.toCharArray();
@@ -1665,7 +1727,7 @@
final int total_size = _canonicalName.length();
final char[] dest_chars = new char[total_size];
final char[] value = _canonicalName.toCharArray();
- final int offset = _domain_length+1;
+ final int offset = getDomainLength() + 1;
// copy "domain:" into dest_chars
//
@@ -1675,7 +1737,7 @@
final int end = writeKeyPropertyListString(value,dest_chars,offset);
// Add ",*" if necessary
- if (_property_list_pattern) {
+ if (isPropertyListPattern()) {
if (end == offset) {
// Property list string is empty.
dest_chars[end] = '*';
@@ -1737,8 +1799,8 @@
if (_ca_array.length == 0) return "";
int len = _canonicalName.length();
- if (_property_list_pattern) len -= 2;
- return _canonicalName.substring(_domain_length +1, len);
+ if (isPropertyListPattern()) len -= 2;
+ return _canonicalName.substring(getDomainLength() + 1, len);
}
// Category : Getter methods <===================================
@@ -1944,22 +2006,18 @@
if (name == null) throw new NullPointerException();
- if (name._domain_pattern ||
- name._property_list_pattern ||
- name._property_value_pattern)
+ if (name.isPattern())
return false;
// No pattern
- if (!_domain_pattern &&
- !_property_list_pattern &&
- !_property_value_pattern)
+ if (!isPattern())
return _canonicalName.equals(name._canonicalName);
return matchDomains(name) && matchKeys(name);
}
private final boolean matchDomains(ObjectName name) {
- if (_domain_pattern) {
+ if (isDomainPattern()) {
// wildmatch domains
// This ObjectName is the pattern
// The other ObjectName is the string.
@@ -1972,15 +2030,15 @@
// If key property value pattern but not key property list
// pattern, then the number of key properties must be equal
//
- if (_property_value_pattern &&
- !_property_list_pattern &&
+ if (isPropertyValuePattern() &&
+ !isPropertyListPattern() &&
(name._ca_array.length != _ca_array.length))
return false;
// If key property value pattern or key property list pattern,
// then every property inside pattern should exist in name
//
- if (_property_value_pattern || _property_list_pattern) {
+ if (isPropertyPattern()) {
final Map<String,String> nameProps = name._getKeyPropertyList();
final Property[] props = _ca_array;
final String cn = _canonicalName;
@@ -1996,7 +2054,7 @@
if (v == null) return false;
// If this property is ok (same key, same value), go to next
//
- if (_property_value_pattern && (p instanceof PatternProperty)) {
+ if (isPropertyValuePattern() && (p instanceof PatternProperty)) {
// wildmatch key property values
// p is the property pattern, v is the string
if (Util.wildmatch(v,p.getValueString(cn)))
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java Mon Sep 14 07:03:04 2015 +0000
@@ -132,7 +132,9 @@
* Checks if this Kerberos delegation permission object "implies" the
* specified permission.
* <P>
- * If none of the above are true, {@code implies} returns false.
+ * This method returns true if this {@code DelegationPermission}
+ * is equal to {@code p}, and returns false otherwise.
+ *
* @param p the permission to check against.
*
* @return true if the specified permission is implied by this object,
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java Mon Sep 14 07:03:04 2015 +0000
@@ -179,7 +179,16 @@
* Checks if this Kerberos service permission object "implies" the
* specified permission.
* <P>
- * If none of the above are true, {@code implies} returns false.
+ * More specifically, this method returns true if all of the following
+ * are true (and returns false if any of them are not):
+ * <ul>
+ * <li> <i>p</i> is an instanceof {@code ServicePermission},
+ * <li> <i>p</i>'s actions are a proper subset of this
+ * {@code ServicePermission}'s actions,
+ * <li> <i>p</i>'s name is equal to this {@code ServicePermission}'s name
+ * or this {@code ServicePermission}'s name is "*".
+ * </ul>
+ *
* @param p the permission to check against.
*
* @return true if the specified permission is implied by this object,
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java Mon Sep 14 07:03:04 2015 +0000
@@ -4467,4 +4467,4 @@
static final long serialVersionUID = 4886719666485113312L;
-} //end class
\ No newline at end of file
+} //end class
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetFactory.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetFactory.java Mon Sep 14 07:03:04 2015 +0000
@@ -96,4 +96,4 @@
*/
public WebRowSet createWebRowSet() throws SQLException;
-}
\ No newline at end of file
+}
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
<HTML><HEAD></HEAD><BODY><P>
algorithm factories.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
<HTML><HEAD></HEAD><BODY><P>
basic handlers for elements that can occur inside <CODE>ds:KeyValue</CODE>.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
<HTML><HEAD></HEAD><BODY><P>
basic handlers for elements that can occur inside <CODE>ds:KeyInfo</CODE>.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
<HTML><HEAD></HEAD><BODY><P>
basic handlers for elements that can occur inside <CODE>ds:X509Data</CODE>.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
<HTML><HEAD></HEAD><BODY><P>
implementations for retrieval of certificates and public keys from elements.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
<HTML><HEAD></HEAD><BODY><P>
the resolver framework for retrieval of certificates and public keys from elements.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
<HTML><HEAD></HEAD><BODY><P>
implementations of resolvers for retrieval for certificates and public keys from user-specified locations.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/package.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/package.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
<HTML><HEAD></HEAD><BODY><P>
a resolver framework for certificates and public keys from user-specified locations.
-</P></BODY></HTML>
\ No newline at end of file
+</P></BODY></HTML>
--- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/TransformParam.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/TransformParam.java Mon Sep 14 07:03:04 2015 +0000
@@ -24,4 +24,4 @@
package com.sun.org.apache.xml.internal.security.transforms;
public interface TransformParam {
-}
\ No newline at end of file
+}
--- a/jdk/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c Mon Sep 14 07:03:04 2015 +0000
@@ -77,14 +77,17 @@
static int get_totalticks(int which, ticks *pticks) {
FILE *fh;
uint64_t userTicks, niceTicks, systemTicks, idleTicks;
+ uint64_t iowTicks = 0, irqTicks = 0, sirqTicks= 0;
int n;
if((fh = fopen("/proc/stat", "r")) == NULL) {
return -1;
}
- n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64,
- &userTicks, &niceTicks, &systemTicks, &idleTicks);
+ n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 " "
+ DEC_64 " " DEC_64,
+ &userTicks, &niceTicks, &systemTicks, &idleTicks,
+ &iowTicks, &irqTicks, &sirqTicks);
// Move to next line
next_line(fh);
@@ -93,24 +96,30 @@
if (which != -1) {
int i;
for (i = 0; i < which; i++) {
- if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, &userTicks, &niceTicks, &systemTicks, &idleTicks) != 4) {
+ if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 " "
+ DEC_64 " " DEC_64 " " DEC_64,
+ &userTicks, &niceTicks, &systemTicks, &idleTicks,
+ &iowTicks, &irqTicks, &sirqTicks) < 4) {
fclose(fh);
return -2;
}
next_line(fh);
}
- n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 "\n",
- &userTicks, &niceTicks, &systemTicks, &idleTicks);
+ n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 " "
+ DEC_64 " " DEC_64 " " DEC_64 "\n",
+ &userTicks, &niceTicks, &systemTicks, &idleTicks,
+ &iowTicks, &irqTicks, &sirqTicks);
}
fclose(fh);
- if (n != 4) {
+ if (n < 4) {
return -2;
}
pticks->used = userTicks + niceTicks;
- pticks->usedKernel = systemTicks;
- pticks->total = userTicks + niceTicks + systemTicks + idleTicks;
+ pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
+ pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
+ iowTicks + irqTicks + sirqTicks;
return 0;
}
--- a/jdk/src/sample/share/annotations/DependencyChecker/PluginChecker/src/checker/Kettle.xml Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/sample/share/annotations/DependencyChecker/PluginChecker/src/checker/Kettle.xml Mon Sep 14 07:03:04 2015 +0000
@@ -54,4 +54,4 @@
<value>4</value>
</entry>
</supportedModules>
-</device>
\ No newline at end of file
+</device>
--- a/jdk/src/sample/share/annotations/index.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/sample/share/annotations/index.html Mon Sep 14 07:03:04 2015 +0000
@@ -64,4 +64,4 @@
Sources: <a href="Validator/src/">Validator/src/</a>
</ul>
</body>
-</html>
\ No newline at end of file
+</html>
--- a/jdk/src/sample/share/lambda/BulkDataOperations/index.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/sample/share/lambda/BulkDataOperations/index.html Mon Sep 14 07:03:04 2015 +0000
@@ -46,4 +46,4 @@
Source: <a href="src/WC.java">src/WC.java</a>
</ul>
</body>
-</html>
\ No newline at end of file
+</html>
--- a/jdk/src/sample/share/try-with-resources/index.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/src/sample/share/try-with-resources/index.html Mon Sep 14 07:03:04 2015 +0000
@@ -33,4 +33,4 @@
</ul>
</body>
-</html>
\ No newline at end of file
+</html>
--- a/jdk/test/ProblemList.txt Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/ProblemList.txt Mon Sep 14 07:03:04 2015 +0000
@@ -319,6 +319,9 @@
# jdk_time
+# 8134979
+java/time/tck/java/time/chrono/TCKJapaneseChronology.java generic-all
+
############################################################################
# jdk_tools
@@ -384,6 +387,11 @@
# 6456333
sun/tools/jps/TestJpsJarRelative.java generic-all
+# 8134420
+sun/tools/jps/TestJpsClass.java generic-all
+sun/tools/jps/TestJpsJar.java generic-all
+sun/tools/jps/TestJpsSanity.java generic-all
+
# 6734748
sun/tools/jinfo/JInfoRunningProcessFlagTest.java generic-all
--- a/jdk/test/TEST.ROOT Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/TEST.ROOT Mon Sep 14 07:03:04 2015 +0000
@@ -18,7 +18,7 @@
othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces javax/xml/jaxp/testng/validation java/lang/ProcessHandle
# Tests that cannot run concurrently
-exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream javax/rmi sun/tools/jps
+exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream javax/rmi
# Group definitions
groups=TEST.groups [closed/TEST.groups]
--- a/jdk/test/com/sun/awt/SecurityWarning/GetSizeShouldNotReturnZero.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/awt/SecurityWarning/GetSizeShouldNotReturnZero.java Mon Sep 14 07:03:04 2015 +0000
@@ -374,5 +374,3 @@
}
}// TestDialog class
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/Blowfish/TestCipherBlowfish.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import java.security.NoSuchAlgorithmException;
+
+/*
+ * @test
+ * @bug 8048601
+ * @library ../
+ * @summary Test Blowfish cipher with different MODES and padding
+ */
+
+public class TestCipherBlowfish extends TestCipher {
+
+ TestCipherBlowfish() throws NoSuchAlgorithmException {
+ super("Blowfish",
+ new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC",
+ //CFBx
+ "CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56",
+ "CFB64",
+ //OFBx
+ "OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56",
+ "OFB64"},
+ new String[]{"NoPaDDing", "PKCS5Padding"},
+ true);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new TestCipherBlowfish().runAll();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/DES/TestCipherDES.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8048601
+ * @library ../
+ * @summary Test DES/DESede cipher with different MODES and padding
+ */
+
+public class TestCipherDES extends TestCipher {
+
+ TestCipherDES() {
+ super("DES",
+ new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC",
+ //CFBx
+ "CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56",
+ "CFB64",
+ //OFBx
+ "OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56",
+ "OFB64"},
+ new String[]{"NoPaDDing", "PKCS5Padding"});
+ }
+
+ public static void main(String[] args) throws Exception {
+ new TestCipherDES().runAll();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/DES/TestCipherDESede.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8048601
+ * @library ../
+ * @summary Test DES/DESede cipher with different MODES and padding
+ */
+
+public class TestCipherDESede extends TestCipher {
+
+ TestCipherDESede() {
+ super("DESede",
+ new String[]{"CBC", "CTR", "CTS", "ECB", "PCBC",
+ //CFBx
+ "CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40", "CFB48", "CFB56",
+ "CFB64",
+ //OFBx
+ "OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56",
+ "OFB64"},
+ new String[]{"NoPaDDing", "PKCS5Padding"});
+ }
+
+ public static void main(String[] args) throws Exception {
+ new TestCipherDESede().runAll();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBE.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import static java.lang.System.out;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Arrays;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+
+/*
+ * @test
+ * @bug 8048601
+ * @summary Tests for PBE ciphers
+ */
+public class TestCipherPBE {
+
+ private static final String[] ALGORITHMS = {"PBEWithMD5AndDES",
+ "PBEWithMD5AndDES/CBC/PKCS5Padding", "PBEWithMD5AndTripleDES",
+ "PBEWithMD5AndTripleDES/CBC/PKCS5Padding"};
+
+ private static final String KEY_ALGO = "pbeWithMD5ANDdes";
+ private final byte[] SALT;
+ private final byte[] PLAIN_TEXT;
+
+ public TestCipherPBE() {
+ SALT = generateBytes(8);
+ PLAIN_TEXT = generateBytes(200);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ new TestCipherPBE().runAll();
+ }
+
+ private void runAll() throws Exception {
+ for (String algorithm : ALGORITHMS) {
+ runTest(algorithm);
+ }
+ }
+
+ private void runTest(String algorithm)
+ throws InvalidKeySpecException, NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException, ShortBufferException,
+ NoSuchPaddingException, IllegalBlockSizeException,
+ BadPaddingException, InvalidKeyException {
+
+ out.println("=> Testing: " + algorithm);
+
+ try {
+ // Initialization
+ AlgorithmParameterSpec algoParamSpec
+ = new PBEParameterSpec(SALT, 6);
+
+ SecretKey secretKey
+ = SecretKeyFactory.getInstance(KEY_ALGO).generateSecret(
+ new PBEKeySpec(("Secret Key Value").toCharArray()));
+
+ Cipher ci = Cipher.getInstance(algorithm);
+ ci.init(Cipher.ENCRYPT_MODE, secretKey, algoParamSpec);
+
+ // Encryption
+ byte[] cipherText = ci.doFinal(PLAIN_TEXT);
+
+ // Decryption
+ ci.init(Cipher.DECRYPT_MODE, secretKey, algoParamSpec);
+ byte[] recoveredText = ci.doFinal(cipherText);
+
+ if (algorithm.contains("TripleDES")) {
+ throw new RuntimeException(
+ "Expected InvalidKeyException exception uncaugh");
+ }
+
+ // Comparison
+ if (!Arrays.equals(PLAIN_TEXT, recoveredText)) {
+ throw new RuntimeException(
+ "Test failed: plainText is not equal to recoveredText");
+ }
+ out.println("Test Passed.");
+ } catch (InvalidKeyException ex) {
+ if (algorithm.contains("TripleDES")) {
+ out.println("Expected InvalidKeyException raised");
+ } else {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ public static byte[] generateBytes(int length) {
+ byte[] bytes = new byte[length];
+ for (int i = 0; i < length; i++) {
+ bytes[i] = (byte) (i & 0xff);
+ }
+ return bytes;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import static java.lang.System.out;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * This is a abstract class used to test various ciphers
+ */
+public abstract class TestCipher {
+
+ private final String SUNJCE = "SunJCE";
+ private final String ALGORITHM;
+ private final String[] MODES;
+ private final String[] PADDINGS;
+
+ /* Used to test cipher with different key strengths
+ Key size tested is increment of KEYCUTTER from MINIMUM_KEY_SIZE to
+ maximum allowed keysize.
+ DES/DESede/Blowfish work with currently selected key sizes.
+ */
+ private final int variousKeySize;
+ private final int KEYCUTTER = 8;
+ private final int MINIMUM_KEY_SIZE = 32;
+
+ // Used to assert that Encryption/Decryption works with same buffer
+ // TEXT_LEN is multiple of blocks in order to work against ciphers w/ NoPadding
+ private final int TEXT_LEN = 800;
+ private final int ENC_OFFSET = 6;
+ private final int STORAGE_OFFSET = 3;
+ private final int PAD_BYTES = 16;
+
+ private final byte[] IV;
+ private final byte[] INPUT_TEXT;
+
+ TestCipher(String algo, String[] modes, String[] paddings,
+ boolean keyStrength) throws NoSuchAlgorithmException {
+ ALGORITHM = algo;
+ MODES = modes;
+ PADDINGS = paddings;
+ this.variousKeySize
+ = keyStrength ? Cipher.getMaxAllowedKeyLength(ALGORITHM) : 0;
+
+ IV = generateBytes(8);
+ INPUT_TEXT = generateBytes(TEXT_LEN + PAD_BYTES + ENC_OFFSET);
+ }
+
+ TestCipher(String algo, String[] modes, String[] paddings) {
+ ALGORITHM = algo;
+ MODES = modes;
+ PADDINGS = paddings;
+ variousKeySize = 0;
+
+ IV = generateBytes(8);
+ INPUT_TEXT = generateBytes(TEXT_LEN + PAD_BYTES + ENC_OFFSET);
+ }
+
+ private static byte[] generateBytes(int length) {
+ byte[] bytes = new byte[length];
+ for (int i = 0; i < length; i++) {
+ bytes[i] = (byte) (i & 0xff);
+ }
+ return bytes;
+ }
+
+ private boolean isKeyStrenthSupported() {
+ return (variousKeySize != 0);
+ }
+
+ public void runAll() throws InvalidKeyException,
+ NoSuchPaddingException, InvalidAlgorithmParameterException,
+ ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException, NoSuchAlgorithmException,
+ NoSuchProviderException {
+
+ for (String mode : MODES) {
+ for (String padding : PADDINGS) {
+ if (!isKeyStrenthSupported()) {
+ runTest(mode, padding, 0);
+ } else {
+ int keySize = variousKeySize;
+ while (keySize >= MINIMUM_KEY_SIZE) {
+ out.println("With Key Strength: " + keySize);
+ runTest(mode, padding, keySize);
+ keySize -= KEYCUTTER;
+ }
+ }
+ }
+ }
+ }
+
+ private void runTest(String mo, String pad, int keySize)
+ throws NoSuchPaddingException, BadPaddingException,
+ ShortBufferException, IllegalBlockSizeException,
+ InvalidAlgorithmParameterException, InvalidKeyException,
+ NoSuchAlgorithmException, NoSuchProviderException {
+
+ String TRANSFORMATION = ALGORITHM + "/" + mo + "/" + pad;
+ out.println("Testing: " + TRANSFORMATION);
+
+ // Initialization
+ Cipher ci = Cipher.getInstance(TRANSFORMATION, SUNJCE);
+ KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM, SUNJCE);
+ if (keySize != 0) {
+ kg.init(keySize);
+ }
+ SecretKey key = kg.generateKey();
+ SecretKeySpec skeySpec = new SecretKeySpec(key.getEncoded(), ALGORITHM);
+
+ AlgorithmParameterSpec aps = new IvParameterSpec(IV);
+ if (mo.equalsIgnoreCase("ECB")) {
+ ci.init(Cipher.ENCRYPT_MODE, key);
+ } else {
+ ci.init(Cipher.ENCRYPT_MODE, key, aps);
+ }
+
+ // Encryption
+ int PAD_LEN = 0;
+ if (pad.equalsIgnoreCase("PKCS5Padding")) {
+ // Need to consider pad bytes
+ PAD_LEN = 8;
+ }
+
+ byte[] plainText = INPUT_TEXT.clone();
+
+ // Generate cipher and save to separate buffer
+ byte[] cipherText = ci.doFinal(INPUT_TEXT, ENC_OFFSET, TEXT_LEN);
+
+ // Generate cipher and save to same buffer
+ int offset = ci.update(
+ INPUT_TEXT, ENC_OFFSET, TEXT_LEN, INPUT_TEXT, STORAGE_OFFSET);
+ ci.doFinal(INPUT_TEXT, offset + STORAGE_OFFSET);
+
+ if (!equalsBlock(
+ INPUT_TEXT, STORAGE_OFFSET, cipherText, 0, cipherText.length)) {
+ throw new RuntimeException(
+ "Different ciphers generated with same buffer");
+ }
+
+ // Decryption
+ if (mo.equalsIgnoreCase("ECB")) {
+ ci.init(Cipher.DECRYPT_MODE, skeySpec);
+ } else {
+ ci.init(Cipher.DECRYPT_MODE, skeySpec, aps);
+ }
+
+ // Recover text from cipher and save to separate buffer
+ byte[] recoveredText = ci.doFinal(cipherText, 0, cipherText.length);
+
+ if (!equalsBlock(
+ plainText, ENC_OFFSET, recoveredText, 0,
+ recoveredText.length)) {
+ throw new RuntimeException(
+ "Recovered text not same as plain text");
+ } else {
+ out.println("Recovered and plain text are same");
+ }
+
+ // Recover text from cipher and save to same buffer
+ ci.update(INPUT_TEXT, STORAGE_OFFSET, TEXT_LEN + PAD_LEN, INPUT_TEXT,
+ ENC_OFFSET);
+ ci.doFinal(INPUT_TEXT, ENC_OFFSET);
+
+ if (!equalsBlock(
+ plainText, ENC_OFFSET, recoveredText, 0,
+ recoveredText.length)) {
+ throw new RuntimeException(
+ "Recovered text not same as plain text with same buffer");
+ } else {
+ out.println("Recovered and plain text are same with same buffer");
+ }
+
+ out.println("Test Passed.");
+ }
+
+ private static boolean equalsBlock(byte[] b1, int off1, byte[] b2, int off2,
+ int len) {
+ for (int i = off1, j = off2, k = 0; k < len; i++, j++, k++) {
+ if (b1[i] != b2[j]) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/TextLength/DESCipherWrapper.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import static java.lang.System.out;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * Wrapper class to test a given DES algorithm.
+ */
+public class DESCipherWrapper {
+
+ private final Cipher ci;
+ private final byte[] iv;
+ private final SecretKey key;
+ private final String algo;
+ private final String mode;
+ private final String pad;
+ private final int keyStrength;
+ private byte[] resultText = null;
+
+ public DESCipherWrapper(String algo, String mode, String pad)
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ ci = Cipher.getInstance(algo + "/" + mode + "/" + pad);
+
+ iv = new byte[8];
+ for (int i = 0; i < 8; i++) {
+ iv[i] = (byte) (i & 0xff);
+ }
+
+ KeyGenerator kg = KeyGenerator.getInstance(algo);
+ key = kg.generateKey();
+ keyStrength = algo.equalsIgnoreCase("DESede") ? 112
+ : key.getEncoded().length * 8;
+
+ this.algo = algo;
+ this.mode = mode;
+ this.pad = pad;
+ }
+
+ public byte[] getResult() {
+ return resultText.clone();
+ }
+
+ public void execute(int edMode, byte[] inputText)
+ throws InvalidKeyException, InvalidAlgorithmParameterException,
+ IllegalBlockSizeException, BadPaddingException,
+ ShortBufferException, NoSuchAlgorithmException {
+ AlgorithmParameterSpec aps = null;
+
+ try {
+ if (!mode.equalsIgnoreCase("ECB")) {
+ aps = new IvParameterSpec(iv);
+ }
+ ci.init(edMode, key, aps);
+
+ // Generate a resultText using a single-part enc/dec
+ resultText = ci.doFinal(inputText);
+
+ // Generate outputText for each multi-part en/de-cryption
+ /* Combination #1:
+ update(byte[], int, int)
+ doFinal(byte[], int, int)
+ */
+ byte[] part11 = ci.update(inputText, 0, inputText.length);
+ byte[] part12 = ci.doFinal();
+ byte[] outputText1 = new byte[part11.length + part12.length];
+ System.arraycopy(part11, 0, outputText1, 0, part11.length);
+ System.arraycopy(part12, 0, outputText1, part11.length,
+ part12.length);
+
+ List<byte[]> outputTexts = new ArrayList<>(4);
+ outputTexts.add(outputText1);
+
+ /* Combination #2:
+ update(byte[], int, int)
+ doFinal(byte[], int, int, byte[], int)
+ */
+ byte[] part21 = ci.update(inputText, 0, inputText.length - 5);
+ byte[] part22 = new byte[ci.getOutputSize(inputText.length)];
+ int len2 = ci
+ .doFinal(inputText, inputText.length - 5, 5, part22, 0);
+ byte[] outputText2 = new byte[part21.length + len2];
+ System.arraycopy(part21, 0, outputText2, 0, part21.length);
+ System.arraycopy(part22, 0, outputText2, part21.length, len2);
+
+ outputTexts.add(outputText2);
+
+ /* Combination #3:
+ update(byte[], int, int, byte[], int)
+ doFinal(byte[], int, int)
+ */
+ byte[] part31 = new byte[ci.getOutputSize(inputText.length)];
+ int len3 = ci.update(inputText, 0, inputText.length - 8, part31, 0);
+ byte[] part32 = ci.doFinal(inputText, inputText.length - 8, 8);
+ byte[] outputText3 = new byte[len3 + part32.length];
+ System.arraycopy(part31, 0, outputText3, 0, len3);
+ System.arraycopy(part32, 0, outputText3, len3, part32.length);
+
+ outputTexts.add(outputText3);
+
+ /* Combination #4:
+ update(byte[], int, int, byte[], int)
+ doFinal(byte[], int, int, byte[], int)
+ */
+ byte[] part41 = new byte[ci.getOutputSize(inputText.length)];
+ int len4 = ci.update(inputText, 0, inputText.length - 8, part41, 0);
+ int rest4 = ci.doFinal(inputText, inputText.length - 8, 8, part41,
+ len4);
+ byte[] outputText4 = new byte[len4 + rest4];
+ System.arraycopy(part41, 0, outputText4, 0, outputText4.length);
+
+ outputTexts.add(outputText4);
+
+ // Compare results
+ for (int k = 0; k < outputTexts.size(); k++) {
+ if (!Arrays.equals(resultText, outputTexts.get(k))) {
+ out.println(" Testing: " + algo + "/" + mode + "/" + pad);
+ throw new RuntimeException(
+ "Compare value of resultText and combination " + k
+ + " are not same. Test failed.");
+ }
+ }
+ if (keyStrength > Cipher.getMaxAllowedKeyLength(algo)) {
+ throw new RuntimeException(
+ "Expected exception uncaught, keyStrength "
+ + keyStrength);
+ }
+ } catch (InvalidKeyException ex) {
+ if (keyStrength <= Cipher.getMaxAllowedKeyLength(algo)) {
+ out.println("Unexpected exception in " + algo + "/" + mode
+ + "/" + pad + " , KeySize " + keyStrength);
+ throw ex;
+ }
+ out.println("Caught InvalidKeyException as expected");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/TextLength/PBECipherWrapper.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * PBECipherWrapper is the abstract class for all concrete PBE Cipher wrappers.
+ */
+public abstract class PBECipherWrapper {
+
+ public static final int ITERATION_COUNT = 1000;
+ private final String algorithm;
+ private final byte[] salt;
+ protected SecretKey key;
+ protected Cipher ci;
+ protected String baseAlgo;
+ protected byte[] resultText = null;
+ protected AlgorithmParameterSpec aps = null;
+
+ public PBECipherWrapper(String algorithm, int saltSize) {
+ this.algorithm = algorithm;
+ baseAlgo = algorithm.split("/")[0].toUpperCase();
+ salt = generateSalt(saltSize);
+ }
+
+ protected abstract void initCipher(int mode) throws InvalidKeyException,
+ InvalidAlgorithmParameterException, InvalidParameterSpecException;
+
+ public void execute(int edMode, byte[] inputText)
+ throws InvalidAlgorithmParameterException,
+ InvalidParameterSpecException, IllegalBlockSizeException,
+ BadPaddingException, ShortBufferException, InvalidKeyException {
+ // Initialize
+ initCipher(edMode);
+
+ // Generate a resultText using a single-part enc/dec
+ resultText = ci.doFinal(inputText);
+
+ // Generate outputText for each multi-part en/de-cryption
+ /* Combination #1:
+ update(byte[], int, int)
+ doFinal(byte[], int, int)
+ */
+ byte[] part11 = ci.update(inputText, 0, inputText.length);
+ byte[] part12 = ci.doFinal();
+ byte[] outputText1 = new byte[part11.length + part12.length];
+ System.arraycopy(part11, 0, outputText1, 0, part11.length);
+ System.arraycopy(part12, 0, outputText1, part11.length, part12.length);
+
+ List<byte[]> outputTexts = new ArrayList<>(4);
+ outputTexts.add(outputText1);
+
+ /* Combination #2:
+ update(byte[], int, int)
+ doFinal(byte[], int, int, byte[], int)
+ */
+ byte[] part21 = ci.update(inputText, 0, inputText.length - 5);
+ byte[] part22 = new byte[ci.getOutputSize(inputText.length)];
+ int len2 = ci.doFinal(inputText, inputText.length - 5, 5, part22, 0);
+ byte[] outputText2 = new byte[part21.length + len2];
+ System.arraycopy(part21, 0, outputText2, 0, part21.length);
+ System.arraycopy(part22, 0, outputText2, part21.length, len2);
+
+ outputTexts.add(outputText2);
+
+ /* Combination #3:
+ update(byte[], int, int, byte[], int)
+ doFinal(byte[], int, int)
+ */
+ byte[] part31 = new byte[ci.getOutputSize(inputText.length)];
+ int len3 = ci.update(inputText, 0, inputText.length - 8, part31, 0);
+ byte[] part32 = ci.doFinal(inputText, inputText.length - 8, 8);
+ byte[] outputText3 = new byte[len3 + part32.length];
+ System.arraycopy(part31, 0, outputText3, 0, len3);
+ System.arraycopy(part32, 0, outputText3, len3, part32.length);
+
+ outputTexts.add(outputText3);
+
+ /* Combination #4:
+ update(byte[], int, int, byte[], int)
+ doFinal(byte[], int, int, byte[], int)
+ */
+ byte[] part41 = new byte[ci.getOutputSize(inputText.length)];
+ int len4 = ci.update(inputText, 0, inputText.length - 8, part41, 0);
+ int rest4 = ci
+ .doFinal(inputText, inputText.length - 8, 8, part41, len4);
+ byte[] outputText4 = new byte[len4 + rest4];
+ System.arraycopy(part41, 0, outputText4, 0, outputText4.length);
+
+ outputTexts.add(outputText4);
+
+ // Compare results
+ for (int k = 0; k < outputTexts.size(); k++) {
+ if (!Arrays.equals(resultText, outputTexts.get(k))) {
+ throw new RuntimeException(
+ "Compare value of resultText and combination " + k
+ + " are not same. Test failed.");
+ }
+ }
+
+ }
+
+ public final byte[] generateSalt(int numberOfBytes) {
+ byte[] aSalt = new byte[numberOfBytes];
+ for (int i = 0; i < numberOfBytes; i++) {
+ aSalt[i] = (byte) (i & 0xff);
+ }
+ return aSalt;
+ }
+
+ public byte[] getResult() {
+ return resultText;
+ }
+
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ public byte[] getSalt() {
+ return salt;
+ }
+
+ /**
+ * Wrapper class to test a given SecretKeyFactory.PBKDF2 algorithm.
+ */
+ public static class PBKDF2 extends PBECipherWrapper {
+
+ private static final int PBKDF2_SALT_SIZE = 64;
+ private static final int CIPHER_KEY_SIZE = 128;
+ private static final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
+ private static final String KEY_ALGORITHM = "AES";
+ private byte[] iv = null;
+
+ public PBKDF2(String algo, String passwd)
+ throws InvalidKeySpecException, NoSuchAlgorithmException,
+ NoSuchPaddingException {
+ super(algo, PBKDF2_SALT_SIZE);
+
+ ci = Cipher.getInstance(CIPHER_TRANSFORMATION);
+
+ PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray(), getSalt(),
+ ITERATION_COUNT, CIPHER_KEY_SIZE);
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algo);
+ key = keyFactory.generateSecret(pbeKeySpec);
+ }
+
+ @Override
+ protected void initCipher(int mode) throws InvalidKeyException,
+ InvalidAlgorithmParameterException, InvalidParameterSpecException {
+ if (Cipher.ENCRYPT_MODE == mode) {
+ ci.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getEncoded(),
+ KEY_ALGORITHM));
+ iv = ci.getParameters().getParameterSpec(IvParameterSpec.class)
+ .getIV();
+ } else {
+ ci.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getEncoded(),
+ KEY_ALGORITHM), new IvParameterSpec(iv));
+ }
+ }
+ }
+
+ /**
+ * Wrapper class to test a given AES-based PBE algorithm.
+ */
+ public static class AES extends PBECipherWrapper {
+
+ private AlgorithmParameters pbeParams;
+
+ public AES(String algo, String passwd)
+ throws NoSuchAlgorithmException, NoSuchPaddingException,
+ InvalidKeySpecException {
+ super(algo, 0);
+
+ ci = Cipher.getInstance(algo);
+
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(algo);
+ key = skf.generateSecret(new PBEKeySpec(passwd.toCharArray()));
+ }
+
+ @Override
+ protected void initCipher(int mode) throws InvalidKeyException,
+ InvalidAlgorithmParameterException, InvalidParameterSpecException {
+ if (Cipher.ENCRYPT_MODE == mode) {
+ ci.init(Cipher.ENCRYPT_MODE, key);
+ pbeParams = ci.getParameters();
+ } else {
+ ci.init(Cipher.DECRYPT_MODE, key, pbeParams);
+ }
+ }
+ }
+
+ /**
+ * Wrapper class to test a given PBE algorithm.
+ */
+ public static class Legacy extends PBECipherWrapper {
+
+ private static final int PBE_SALT_SIZE = 8;
+
+ public Legacy(String algo, String passwd)
+ throws NoSuchAlgorithmException, NoSuchPaddingException,
+ InvalidKeySpecException {
+ super(algo, PBE_SALT_SIZE);
+
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(algo.split("/")[0]);
+ key = skf.generateSecret(new PBEKeySpec(passwd.toCharArray()));
+
+ aps = new PBEParameterSpec(getSalt(), ITERATION_COUNT);
+
+ ci = Cipher.getInstance(algo);
+ }
+
+ @Override
+ protected void initCipher(int mode) throws InvalidKeyException,
+ InvalidAlgorithmParameterException, InvalidParameterSpecException {
+ ci.init(mode, key, aps);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/TextLength/TestCipherTextLength.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import static java.lang.System.out;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+
+/*
+ * @test
+ * @bug 8048601
+ * @summary Performs multiple-part encryption/decryption depending on the
+ * specified encryption mode and check if the results obtained by
+ * different ways are the same.
+ */
+public class TestCipherTextLength {
+
+ /* Algorithms tested by DESCipherWrapper */
+ private static final String[] DES_ALGORITHMS = {"DES", "DESede",
+ "Blowfish"};
+ private static final String[] DES_MODES = {"ECB", "CBC", "PCBC"};
+ private static final String[] DES_PADDING = {"PKCS5Padding"};
+
+ /* Algorithms tested by PBECipherWrapper */
+ private static final String[] PBE_ALGORITHMS = {"PBEWithMD5AndDES",
+ "PBEWithMD5AndDES/CBC/PKCS5Padding", "PBEWithMD5ANDTripleDES",
+ "PBEWithMD5AndTripleDES/CBC/PKCS5Padding", "PBEwithSHA1AndDESede",
+ "PBEwithSHA1AndDESede/CBC/PKCS5Padding", "PBEwithSHA1AndRC2_40",
+ "PBEwithSHA1Andrc2_40/CBC/PKCS5Padding", "PBEWithSHA1AndRC2_128",
+ "PBEWithSHA1andRC2_128/CBC/PKCS5Padding", "PBEWithSHA1AndRC4_40",
+ "PBEWithsha1AndRC4_40/ECB/NoPadding", "PBEWithSHA1AndRC4_128",
+ "PBEWithSHA1AndRC4_128/ECB/NoPadding", "PBEWithHmacSHA1AndAES_128",
+ "PBEWithHmacSHA224AndAES_128", "PBEWithHmacSHA256AndAES_128",
+ "PBEWithHmacSHA384AndAES_128", "PBEWithHmacSHA512AndAES_128",
+ "PBEWithHmacSHA1AndAES_256", "PBEWithHmacSHA224AndAES_256",
+ "PBEWithHmacSHA256AndAES_256", "PBEWithHmacSHA384AndAES_256",
+ "PBEWithHmacSHA512AndAES_256", "PBKDF2WithHmacSHA1",
+ "PBKDF2WithHmacSHA224", "PBKDF2WithHmacSHA256",
+ "PBKDF2WithHmacSHA384", "PBKDF2WithHmacSHA512"};
+ private static final String PBE_PASSWORD = "Hush, it's a secret!!";
+
+ // Algorithm tested by PBKDF2Wrappter
+ private static final String PBKDF2 = "PBKDF2";
+
+ // Algorithm tested by AESPBEWrapper
+ private static final String AES = "AES";
+
+ public static void main(String[] args) throws Exception {
+ byte[] plainText = new byte[64];
+ for (int i = 0; i < 64; i++) {
+ plainText[i] = (byte) (i & 0xff);
+ }
+
+ new TestCipherTextLength().runAll(plainText);
+ }
+
+ public void runAll(byte[] plainText) throws Exception {
+
+ // Testing DES/Blowfish Cipher
+ for (String algorithm : DES_ALGORITHMS) {
+ for (String desMode : DES_MODES) {
+ for (String padding : DES_PADDING) {
+ out.println("=>Testing: " + algorithm + "/" + desMode
+ + "/" + padding);
+ DESCipherWrapper desCi = new DESCipherWrapper(algorithm,
+ desMode, padding);
+ desCi.execute(Cipher.ENCRYPT_MODE, plainText);
+ desCi.execute(Cipher.DECRYPT_MODE, desCi.getResult());
+ if (!Arrays.equals(plainText, desCi.getResult())) {
+ throw new RuntimeException(
+ "Plain and recovered texts are not same for:"
+ + algorithm + "/" + desMode + "/"
+ + padding);
+ }
+ }
+ }
+ }
+
+ // Testing PBE Cipher
+ for (String algorithm : PBE_ALGORITHMS) {
+ int maxKeyLen = Cipher.getMaxAllowedKeyLength(algorithm);
+ boolean isUnlimited = maxKeyLen == Integer.MAX_VALUE;
+ if (!isUnlimited
+ && (algorithm.contains("TripleDES") || algorithm
+ .contains("AES_256"))) {
+ out.println("Test " + algorithm + " will be ignored");
+ continue;
+ }
+
+ out.println("=>Testing: " + algorithm);
+ PBECipherWrapper pbeCi = createWrapper(algorithm, PBE_PASSWORD);
+ pbeCi.execute(Cipher.ENCRYPT_MODE, plainText);
+ pbeCi.execute(Cipher.DECRYPT_MODE, pbeCi.getResult());
+ if (!Arrays.equals(plainText, pbeCi.getResult())) {
+ throw new RuntimeException(
+ "Plain and recovered texts are not same for:"
+ + algorithm);
+ }
+ }
+ }
+
+ private PBECipherWrapper createWrapper(String algo, String passwd)
+ throws InvalidKeySpecException, NoSuchAlgorithmException,
+ NoSuchPaddingException {
+ if (algo.contains(PBKDF2)) {
+ return new PBECipherWrapper.PBKDF2(algo, passwd);
+ } else if (algo.contains(AES)) {
+ return new PBECipherWrapper.AES(algo, passwd);
+ } else {
+ return new PBECipherWrapper.Legacy(algo, passwd);
+ }
+ }
+}
--- a/jdk/test/com/sun/crypto/provider/Mac/Utils.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/crypto/provider/Mac/Utils.java Mon Sep 14 07:03:04 2015 +0000
@@ -76,4 +76,4 @@
interface MacTest {
void doTest(String alg) throws Exception;
-}
\ No newline at end of file
+}
--- a/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -442,6 +442,3 @@
}
}
}
-
-
-
--- a/jdk/test/com/sun/jdi/ShellScaffold.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/jdi/ShellScaffold.sh Mon Sep 14 07:03:04 2015 +0000
@@ -1215,5 +1215,3 @@
# Don't know how this arises
debuggeeFailIfPresent "Internal exception"
}
-
-
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/ConfigKey.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Client/ConfigKey.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,4 +23,4 @@
public enum ConfigKey {
CONSTANT3, CONSTANT2;
-}
\ No newline at end of file
+}
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/ConfigKey.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/ConfigKey.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,4 +23,4 @@
public enum ConfigKey {
CONSTANT1, CONSTANT2;
-}
\ No newline at end of file
+}
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Ste.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/Ste.java Mon Sep 14 07:03:04 2015 +0000
@@ -29,4 +29,4 @@
public void foo() {
sendNotification(new TestNotification("test", this, count++));
}
-}
\ No newline at end of file
+}
--- a/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/SteMBean.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/jmx/remote/NotificationMarshalVersions/Server/SteMBean.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,4 +23,4 @@
public interface SteMBean {
public void foo();
-}
\ No newline at end of file
+}
--- a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.policy Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.policy Mon Sep 14 07:03:04 2015 +0000
@@ -7,5 +7,3 @@
//permission java.net.SocketPermission "*:636", "connect";
//permission javax.security.auth.AuthPermission "modifyPrincipals";
};
-
-
--- a/jdk/test/java/awt/Component/DimensionEncapsulation/DimensionEncapsulation.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Component/DimensionEncapsulation/DimensionEncapsulation.java Mon Sep 14 07:03:04 2015 +0000
@@ -212,4 +212,4 @@
throw new RuntimeException(e);
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/Component/InsetsEncapsulation/InsetsEncapsulation.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Component/InsetsEncapsulation/InsetsEncapsulation.java Mon Sep 14 07:03:04 2015 +0000
@@ -163,4 +163,4 @@
throw new RuntimeException(e);
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java Mon Sep 14 07:03:04 2015 +0000
@@ -69,4 +69,4 @@
}
});
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.html Mon Sep 14 07:03:04 2015 +0000
@@ -29,4 +29,4 @@
<applet CODE="MultiResolutionCursorTest.class" WIDTH=300 HEIGHT=100></applet>
<p> See the dialog box (usually in upper left corner) for instructions</p>
</body>
-</html>
\ No newline at end of file
+</html>
--- a/jdk/test/java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -134,4 +134,4 @@
throw new RuntimeException("file chooser is underneath");
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/Focus/6981400/Test3.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Focus/6981400/Test3.java Mon Sep 14 07:03:04 2015 +0000
@@ -135,5 +135,3 @@
}
}
}
-
-
--- a/jdk/test/java/awt/FontClass/LCDScale.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/FontClass/LCDScale.java Mon Sep 14 07:03:04 2015 +0000
@@ -79,5 +79,3 @@
}
}
}
-
-
--- a/jdk/test/java/awt/Frame/FramesGC/FramesGC.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Frame/FramesGC/FramesGC.java Mon Sep 14 07:03:04 2015 +0000
@@ -156,4 +156,4 @@
refs.add(new PhantomReference<Frame>(frame, que));
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java Mon Sep 14 07:03:04 2015 +0000
@@ -76,4 +76,4 @@
frame.dispose();
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/MenuBar/RemoveHelpMenu/RemoveHelpMenu.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/MenuBar/RemoveHelpMenu/RemoveHelpMenu.java Mon Sep 14 07:03:04 2015 +0000
@@ -129,4 +129,4 @@
checkMenuCount(menuBar, 0);
checkHelpMenu(helpMenu, false);
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/Mixing/JButtonInGlassPane.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Mixing/JButtonInGlassPane.java Mon Sep 14 07:03:04 2015 +0000
@@ -426,5 +426,3 @@
}
}// TestDialog class
-
-
--- a/jdk/test/java/awt/Mixing/LWComboBox.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Mixing/LWComboBox.java Mon Sep 14 07:03:04 2015 +0000
@@ -421,5 +421,3 @@
}
}// TestDialog class
-
-
--- a/jdk/test/java/awt/Mixing/MixingInHwPanel.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Mixing/MixingInHwPanel.java Mon Sep 14 07:03:04 2015 +0000
@@ -424,5 +424,3 @@
}
}// TestDialog class
-
-
--- a/jdk/test/java/awt/Mixing/MixingOnShrinkingHWButton.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Mixing/MixingOnShrinkingHWButton.java Mon Sep 14 07:03:04 2015 +0000
@@ -425,5 +425,3 @@
}
}// TestDialog class
-
-
--- a/jdk/test/java/awt/Mixing/NonOpaqueInternalFrame.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Mixing/NonOpaqueInternalFrame.java Mon Sep 14 07:03:04 2015 +0000
@@ -430,5 +430,3 @@
}
}// TestDialog class
-
-
--- a/jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -100,4 +100,4 @@
frame.add(panel, BorderLayout.CENTER);
frame.setVisible(true);
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/MouseInfo/JContainerMousePositionTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/MouseInfo/JContainerMousePositionTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -144,5 +144,3 @@
frame1.setVisible(true);
}
}
-
-
--- a/jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Robot/RobotWheelTest/RobotWheelTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -80,4 +80,4 @@
}
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/ScrollPane/bug8077409Test.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/ScrollPane/bug8077409Test.java Mon Sep 14 07:03:04 2015 +0000
@@ -112,4 +112,4 @@
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -148,4 +148,4 @@
"JPopupMenu shown and menu item selected using keyboard");
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/Window/AlwaysOnTop/SyncAlwaysOnTopFieldTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/Window/AlwaysOnTop/SyncAlwaysOnTopFieldTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -59,4 +59,4 @@
window.setVisible(true);
return window;
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/applet/Applet/AppletFlipBuffer.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/applet/Applet/AppletFlipBuffer.java Mon Sep 14 07:03:04 2015 +0000
@@ -52,4 +52,4 @@
frame.dispose();
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/test.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/test.html Mon Sep 14 07:03:04 2015 +0000
@@ -41,4 +41,4 @@
<APPLET CODE="IOExceptionIfEncodedURLTest.class" WIDTH=200 HEIGHT=200></APPLET>
</body>
-</html>
\ No newline at end of file
+</html>
--- a/jdk/test/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -168,4 +168,4 @@
}
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/datatransfer/DataFlavor/XJavaUrlDataFlavorTest/XJavaUrlDataFlavorTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -342,4 +342,4 @@
}
}
-}// TestDialog class
\ No newline at end of file
+}// TestDialog class
--- a/jdk/test/java/awt/datatransfer/MissedHtmlAndRtfBug/MyTransferable.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/datatransfer/MissedHtmlAndRtfBug/MyTransferable.java Mon Sep 14 07:03:04 2015 +0000
@@ -59,4 +59,4 @@
throw new UnsupportedFlavorException(flavor);
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java Mon Sep 14 07:03:04 2015 +0000
@@ -120,5 +120,3 @@
frame.dispatchEvent( ( AWTEvent )meOld );
}
}
-
-
--- a/jdk/test/java/awt/im/4490692/bug4490692.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/im/4490692/bug4490692.html Mon Sep 14 07:03:04 2015 +0000
@@ -59,5 +59,3 @@
<APPLET CODE="bug4490692.class" WIDTH=0 HEIGHT=0></APPLET>
</body>
</html>
-
-
--- a/jdk/test/java/awt/im/4959409/bug4959409.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/awt/im/4959409/bug4959409.html Mon Sep 14 07:03:04 2015 +0000
@@ -45,5 +45,3 @@
<APPLET CODE="bug4959409.class" WIDTH=0 HEIGHT=0></APPLET>
</body>
</html>
-
-
--- a/jdk/test/java/beans/README Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/beans/README Mon Sep 14 07:03:04 2015 +0000
@@ -73,4 +73,4 @@
If this object is not null it will be encoded and decoded.
Also the object updating will be tested in this case.
The test() method has a boolean parameter,
-which indicates that the test should be started in secure context.
\ No newline at end of file
+which indicates that the test should be started in secure context.
--- a/jdk/test/java/beans/SimpleBeanInfo/LoadingStandardIcons/java.policy Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/beans/SimpleBeanInfo/LoadingStandardIcons/java.policy Mon Sep 14 07:03:04 2015 +0000
@@ -1,1 +1,1 @@
-;
\ No newline at end of file
+;
--- a/jdk/test/java/io/Serializable/evolution/AddedSuperClass/README Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/io/Serializable/evolution/AddedSuperClass/README Mon Sep 14 07:03:04 2015 +0000
@@ -12,6 +12,3 @@
rm A.class AddedSuperClass.class
javac ReadAddedSuperClass2.java
java ReadAddedSuperClass2
-
-
-
--- a/jdk/test/java/lang/ClassLoader/getdotresource.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/lang/ClassLoader/getdotresource.sh Mon Sep 14 07:03:04 2015 +0000
@@ -44,5 +44,3 @@
# now start the test
${TESTJAVA}/bin/java ${TESTVMOPTS} -cp ${TESTSRC}${FS}resource.jar${PS}${TESTCLASSES} GetDotResource
-
-
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.sh Mon Sep 14 07:03:04 2015 +0000
@@ -69,5 +69,3 @@
then echo "$failures test(s) failed";
else echo "All test(s) passed"; fi
exit $failures
-
-
--- a/jdk/test/java/net/SocketPermission/policy Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/net/SocketPermission/policy Mon Sep 14 07:03:04 2015 +0000
@@ -1,3 +1,3 @@
grant {
permission java.security.AllPermission;
-};
\ No newline at end of file
+};
--- a/jdk/test/java/nio/channels/SocketChannel/Open.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/nio/channels/SocketChannel/Open.sh Mon Sep 14 07:03:04 2015 +0000
@@ -33,6 +33,3 @@
* )
echo "unrecognized system: $OS" ;;
esac
-
-
-
--- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/README Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/README Mon Sep 14 07:03:04 2015 +0000
@@ -31,5 +31,3 @@
(c) Execute the make script :-
Solaris: gnumake all
Linux: gmake all
-
-
--- a/jdk/test/java/nio/file/Files/probeContentType/ParallelProbes.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/nio/file/Files/probeContentType/ParallelProbes.java Mon Sep 14 07:03:04 2015 +0000
@@ -21,17 +21,18 @@
* questions.
*/
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-
/* @test
* @summary Test probing content type simultaneously from multiple threads.
* @requires (os.family == "linux") | (os.family == "solaris")
* @build ParallelProbes SimpleFileTypeDetector
* @run main/othervm ParallelProbes 10
*/
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+
public class ParallelProbes {
private static final int REPEATS = 1000;
--- a/jdk/test/java/rmi/registry/readTest/readTest.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/rmi/registry/readTest/readTest.sh Mon Sep 14 07:03:04 2015 +0000
@@ -125,5 +125,3 @@
fi
rm -rf OUT.TXT ${RMIREG_OUT} rmi_tmp
exit ${exitCode}
-
-
--- a/jdk/test/java/security/KeyStore/PKCS12/README Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/security/KeyStore/PKCS12/README Mon Sep 14 07:03:04 2015 +0000
@@ -25,4 +25,4 @@
3. Import certificate
<JAVA-HOME>/bin/keytool -import -alias pkcs12test -keystore ks-pkcs.data
--storepass storepass -file pkcs12testCA.cer.data
\ No newline at end of file
+-storepass storepass -file pkcs12testCA.cer.data
--- a/jdk/test/java/security/SignedObject/Copy.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/security/SignedObject/Copy.java Mon Sep 14 07:03:04 2015 +0000
@@ -119,5 +119,3 @@
}
}
}
-
-
--- a/jdk/test/java/util/AbstractCollection/ToArrayTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/util/AbstractCollection/ToArrayTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -211,5 +211,3 @@
else {System.out.println(x + " not equal to " + y); fail(); }
}
}
-
-
--- a/jdk/test/java/util/Arrays/SetAllTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/util/Arrays/SetAllTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -278,4 +278,4 @@
// expected
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/util/Locale/bug4123285.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/util/Locale/bug4123285.html Mon Sep 14 07:03:04 2015 +0000
@@ -1,1 +1,1 @@
-<APPLET CODE="bug4123285.class" CODEBASE="./" WIDTH="250" HEIGHT="325" ALIGN="TOP"></APPLET>
\ No newline at end of file
+<APPLET CODE="bug4123285.class" CODEBASE="./" WIDTH="250" HEIGHT="325" ALIGN="TOP"></APPLET>
--- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -120,4 +120,4 @@
Assert.assertTrue(eOnWhenComplete.get() instanceof CompletionException,
"Incorrect exception passed to whenComplete: " + eOnWhenComplete.get());
}
-}
\ No newline at end of file
+}
--- a/jdk/test/java/util/logging/LogManager/Configuration/TestConfigurationLock.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/util/logging/LogManager/Configuration/TestConfigurationLock.properties Mon Sep 14 07:03:04 2015 +0000
@@ -18,5 +18,3 @@
foo.bar.l10.level = INFO
foo.bar.l100.level = INFO
foo.bar.l1000.level = INFO
-
-
--- a/jdk/test/java/util/stream/bootlib/java/util/stream/DefaultMethodStreams.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/java/util/stream/bootlib/java/util/stream/DefaultMethodStreams.java Mon Sep 14 07:03:04 2015 +0000
@@ -981,4 +981,4 @@
s.close();
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/crypto/SecretKeyFactory/PBKDF2TranslateTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/crypto/SecretKeyFactory/PBKDF2TranslateTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -267,4 +267,4 @@
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/imageio/plugins/shared/CanWriteSequence.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/imageio/plugins/shared/CanWriteSequence.java Mon Sep 14 07:03:04 2015 +0000
@@ -75,4 +75,4 @@
writer.dispose();
ios.close();
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/management/MustBeValidMBeanInfo/logging.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/management/MustBeValidMBeanInfo/logging.properties Mon Sep 14 07:03:04 2015 +0000
@@ -11,4 +11,4 @@
java.util.logging.ConsoleHandler.level = FINEST
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
-javax.management.misc.level = FINEST
\ No newline at end of file
+javax.management.misc.level = FINEST
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/ObjectName/CompressedStorageTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8041565
+ * @summary Tests the limits imposed on the domain name part of an
+ * ObjectName instance
+ * @author Jaroslav Bachorik
+ * @modules java.management
+ * @run main CompressedStorageTest
+ */
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.function.Consumer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+public class CompressedStorageTest {
+ private static Method setDomainLengthM;
+ private static Field compressedStorageFld;
+
+ private static int DOMAIN_PATTERN;
+ private static int PROPLIST_PATTERN;
+ private static int PROPVAL_PATTERN;
+
+ private static Method setDomainPattern;
+ private static Method setPropertyListPattern;
+ private static Method setPropertyValuePattern;
+
+
+ static {
+ try {
+ Class<?> clz = ObjectName.class;
+ setDomainLengthM = clz.getDeclaredMethod("setDomainLength", int.class);
+ setDomainLengthM.setAccessible(true);
+
+ compressedStorageFld = clz.getDeclaredField("_compressed_storage");
+ compressedStorageFld.setAccessible(true);
+
+ setDomainPattern = clz.getDeclaredMethod("setDomainPattern", boolean.class);
+ setDomainPattern.setAccessible(true);
+ setPropertyListPattern = clz.getDeclaredMethod("setPropertyListPattern", boolean.class);
+ setPropertyListPattern.setAccessible(true);
+ setPropertyValuePattern = clz.getDeclaredMethod("setPropertyValuePattern", boolean.class);
+ setPropertyValuePattern.setAccessible(true);
+
+ DOMAIN_PATTERN = getStaticIntFld("DOMAIN_PATTERN");
+ PROPLIST_PATTERN = getStaticIntFld("PROPLIST_PATTERN");
+ PROPVAL_PATTERN = getStaticIntFld("PROPVAL_PATTERN");
+
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ testZeroLength();
+ testNegativeLength();
+ testMaxLength();
+
+ testSetDomainPattern();
+ testSetPropertyListPattern();
+ testSetPropertyValuePattern();
+ }
+
+ private static ObjectName getObjectName()
+ throws MalformedObjectNameException {
+ return new ObjectName("domain", "key", "value");
+ }
+
+ /**
+ * Test for accepting 0 being passed as argument to
+ * {@linkplain ObjectName#setDomainLength(int)}.
+ *
+ */
+ private static void testZeroLength() throws Exception {
+ setDomainNameLength(0);
+ }
+
+ /**
+ * Test for rejecting negative value being passed as argument to
+ * {@linkplain ObjectName#setDomainLength(int)}.
+ */
+ private static void testNegativeLength() throws Exception {
+ try {
+ setDomainNameLength(-1);
+ } catch (MalformedObjectNameException e) {
+ return;
+ }
+ fail("Allowing negative domain name length");
+ }
+
+ /**
+ * Test for rejecting value exceeding the maximum allowed length
+ * being passed as argument to {@linkplain ObjectName#setDomainLength(int)}.
+ */
+ private static void testMaxLength() throws Exception {
+ try {
+ setDomainNameLength(Integer.MAX_VALUE / 4 + 1);
+ } catch (MalformedObjectNameException e) {
+ return;
+ }
+ fail("Maximum domain name length is not respected");
+ }
+
+ /**
+ * Tests that calling {@linkplain ObjectName#setDomainPattern(boolean)}
+ * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}.
+ */
+ private static void testSetDomainPattern() throws Exception {
+ ObjectName on = getObjectName();
+
+ checkMask(DOMAIN_PATTERN, setDomainPattern, on);
+ }
+
+ /**
+ * Tests that calling {@linkplain ObjectName#setPropertyListPattern(boolean)}
+ * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}.
+ */
+ private static void testSetPropertyListPattern() throws Exception {
+ ObjectName on = getObjectName();
+
+ checkMask(PROPLIST_PATTERN, setPropertyListPattern, on);
+ }
+
+ /**
+ * Tests that calling {@linkplain ObjectName#setPropertyValuePattern(boolean)}
+ * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}.
+ */
+ private static void testSetPropertyValuePattern() throws Exception {
+ ObjectName on = getObjectName();
+
+ checkMask(PROPVAL_PATTERN, setPropertyValuePattern, on);
+ }
+
+ /**
+ * Helper method to call {@linkplain ObjectName#setDomainLength(int)}
+ * method via reflection.
+ * @param len The domain name length
+ * @throws MalformedObjectNameException Propagated from
+ * {@linkplain ObjectName#setDomainLength(int)} invocation.
+ */
+ private static void setDomainNameLength(int len)
+ throws MalformedObjectNameException {
+ try {
+ setDomainLengthM.invoke(getObjectName(), len);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof MalformedObjectNameException) {
+ throw (MalformedObjectNameException)cause;
+ }
+ throw new Error(cause);
+ } catch (IllegalAccessException | IllegalArgumentException e) {
+ throw new Error(e);
+ }
+ }
+
+ /**
+ * Helper method to assert that a particular boolean setter affects only
+ * a particular bit in the {@linkplain ObjectName#_compressed_storage} field.
+ * @param mask bitmask for storing the boolean value
+ * @param setter setter method reference
+ * @param on {@linkplain ObjectName} instance
+ */
+ private static void checkMask(int mask, Method setter, ObjectName on)
+ throws Exception {
+ int valBefore = compressedStorageFld.getInt(on);
+ setter.invoke(on, true);
+ int valAfter = compressedStorageFld.getInt(on);
+
+ checkMask(mask, valAfter ^ valBefore);
+
+ valBefore = valAfter;
+ setter.invoke(on, false);
+ valAfter = compressedStorageFld.getInt(on);
+
+ checkMask(mask, valAfter ^ valBefore);
+ }
+
+ /**
+ * Compare the changed bits with the given mask.
+ * @param mask bitmask
+ * @param val the changed bits; may be 0 if there was no change
+ */
+ private static void checkMask(int mask, int val) {
+ if (val != 0 && val != mask) {
+ fail("Invalid mask: expecting '" +
+ Integer.toBinaryString(mask) + "' , received '" +
+ Integer.toBinaryString(val) + "'");
+ }
+ }
+
+ /**
+ * Helper method to obtain the value of a static field via reflection.
+ * @param name static field name
+ * @return static field value
+ */
+ private static int getStaticIntFld(String name) throws Exception {
+ Field fld = ObjectName.class.getDeclaredField(name);
+ fld.setAccessible(true);
+
+ return fld.getInt(null);
+ }
+
+ private static void fail(String msg) {
+ throw new Error(msg);
+ }
+}
--- a/jdk/test/javax/management/modelmbean/SimpleModelMBean/logging.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/management/modelmbean/SimpleModelMBean/logging.properties Mon Sep 14 07:03:04 2015 +0000
@@ -11,4 +11,4 @@
java.util.logging.ConsoleHandler.level = FINEST
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
-javax.management.misc.level = FINEST
\ No newline at end of file
+javax.management.misc.level = FINEST
--- a/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/security/auth/Subject/doAs/policy.expect.ace Mon Sep 14 07:03:04 2015 +0000
@@ -24,4 +24,4 @@
grant codeBase "file:ReadPropertyNegativeAction.jar"
Principal javax.security.auth.x500.X500Principal "cn=Duke" {
permission java.security.AllPermission;
-};
\ No newline at end of file
+};
--- a/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/security/auth/Subject/doAs/policy.one.principal Mon Sep 14 07:03:04 2015 +0000
@@ -33,4 +33,4 @@
permission javax.security.auth.AuthPermission "getSubject";
permission javax.security.auth.AuthPermission "doAs";
permission java.util.PropertyPermission "java.class.path", "read";
-};
\ No newline at end of file
+};
--- a/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/security/auth/Subject/doAs/policy.two.principals Mon Sep 14 07:03:04 2015 +0000
@@ -34,4 +34,4 @@
permission javax.security.auth.AuthPermission "getSubject";
permission javax.security.auth.AuthPermission "doAs";
permission java.util.PropertyPermission "java.class.path", "read";
-};
\ No newline at end of file
+};
--- a/jdk/test/javax/security/auth/login/LoginContext/shared.config Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/security/auth/login/LoginContext/shared.config Mon Sep 14 07:03:04 2015 +0000
@@ -1,4 +1,4 @@
SharedState {
SharedState$FirstModule required;
SharedState$SecondModule required;
-};
\ No newline at end of file
+};
--- a/jdk/test/javax/sound/midi/Gervill/ModelStandardIndexedDirector/ModelStandardIndexedDirectorTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardIndexedDirector/ModelStandardIndexedDirectorTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -184,5 +184,3 @@
}
}
-
-
--- a/jdk/test/javax/swing/JColorChooser/8065098/bug8065098.html Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JColorChooser/8065098/bug8065098.html Mon Sep 14 07:03:04 2015 +0000
@@ -37,4 +37,4 @@
<applet width="500" height="1" code="bug8065098.class">
</applet>
</body>
-</html>
\ No newline at end of file
+</html>
--- a/jdk/test/javax/swing/JFileChooser/8062561/security2.policy Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JFileChooser/8062561/security2.policy Mon Sep 14 07:03:04 2015 +0000
@@ -1,1 +1,1 @@
-// Autogenerated file
\ No newline at end of file
+// Autogenerated file
--- a/jdk/test/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java Mon Sep 14 07:03:04 2015 +0000
@@ -82,4 +82,4 @@
return "CustomFileFilter";
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/JMenu/8072900/WrongSelectionOnMouseOver.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JMenu/8072900/WrongSelectionOnMouseOver.java Mon Sep 14 07:03:04 2015 +0000
@@ -195,4 +195,4 @@
}
System.out.println("Test passed");
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/JMenuBar/MisplacedBorder/MisplacedBorder.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JMenuBar/MisplacedBorder/MisplacedBorder.java Mon Sep 14 07:03:04 2015 +0000
@@ -132,4 +132,4 @@
throw new RuntimeException(e);
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/JOptionPane/8081019/bug8081019.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JOptionPane/8081019/bug8081019.java Mon Sep 14 07:03:04 2015 +0000
@@ -103,4 +103,4 @@
throw new RuntimeException("Exception in the output!");
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt Mon Sep 14 07:03:04 2015 +0000
@@ -219,5 +219,3 @@
Copyright 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
California 95054, U.S.A. All rights reserved.
-
-
--- a/jdk/test/javax/swing/JTree/8072676/TreeClipTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JTree/8072676/TreeClipTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -94,4 +94,4 @@
System.out.println("Passed.");
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java Mon Sep 14 07:03:04 2015 +0000
@@ -381,4 +381,4 @@
return nodesFlavor.equals(flavor);
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/UIDefaults/7180976/Pending.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/UIDefaults/7180976/Pending.java Mon Sep 14 07:03:04 2015 +0000
@@ -47,4 +47,4 @@
UIManager.get("foobar");
passed = true;
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/plaf/basic/BasicLabelUI/bug7172652.java Mon Sep 14 07:03:04 2015 +0000
@@ -169,4 +169,4 @@
frame.setVisible(true);
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/text/View/8015853/bug8015853.txt Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/text/View/8015853/bug8015853.txt Mon Sep 14 07:03:04 2015 +0000
@@ -64,4 +64,4 @@
frame.add(editorPane);
frame.setVisible(<b>true</b>);
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/text/html/8005391/bug8005391.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/text/html/8005391/bug8005391.java Mon Sep 14 07:03:04 2015 +0000
@@ -58,4 +58,4 @@
}
}
}
-}
\ No newline at end of file
+}
--- a/jdk/test/javax/swing/text/html/HTMLDocument/8058120/bug8058120.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/swing/text/html/HTMLDocument/8058120/bug8058120.java Mon Sep 14 07:03:04 2015 +0000
@@ -109,5 +109,3 @@
frame.setVisible(true);
}
}
-
-
--- a/jdk/test/javax/xml/bind/xjc/8032884/optional-property-schema.xsd Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/xml/bind/xjc/8032884/optional-property-schema.xsd Mon Sep 14 07:03:04 2015 +0000
@@ -11,4 +11,4 @@
<xs:element name="foo" type="xs:int" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
-</xs:schema>
\ No newline at end of file
+</xs:schema>
--- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml Mon Sep 14 07:03:04 2015 +0000
@@ -4,4 +4,4 @@
<item uniqueAttr="ONE">2</item>
<item uniqueAttr="TWO">2</item>
<itemRef>3</itemRef>
-</itemList>
\ No newline at end of file
+</itemList>
--- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd Mon Sep 14 07:03:04 2015 +0000
@@ -38,4 +38,4 @@
</xsd:simpleContent>
</xsd:complexType>
-</xsd:schema>
\ No newline at end of file
+</xsd:schema>
--- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml Mon Sep 14 07:03:04 2015 +0000
@@ -1,2 +1,2 @@
<?xml version="1.0"?>
-<S>-12345</S>
\ No newline at end of file
+<S>-12345</S>
--- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml Mon Sep 14 07:03:04 2015 +0000
@@ -2,4 +2,4 @@
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<B />
<C xsi:type="X" />
-</A>
\ No newline at end of file
+</A>
--- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml Mon Sep 14 07:03:04 2015 +0000
@@ -2,4 +2,4 @@
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<B xsi:type="X" />
<C />
-</A>
\ No newline at end of file
+</A>
--- a/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd Mon Sep 14 07:03:04 2015 +0000
@@ -1,2 +1,2 @@
<!NOTATION myNotation SYSTEM "somethingElse" >
-<!ENTITY myUnparsedEntity SYSTEM "something" NDATA myNotation >
\ No newline at end of file
+<!ENTITY myUnparsedEntity SYSTEM "something" NDATA myNotation >
--- a/jdk/test/javax/xml/jaxp/transform/8004476/tokenize.xml Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/javax/xml/jaxp/transform/8004476/tokenize.xml Mon Sep 14 07:03:04 2015 +0000
@@ -4,4 +4,4 @@
<b>Is this EXSLT? No. no</b>
<c>Is this EXSLT? No. no</c>
</a>
-</html>
\ No newline at end of file
+</html>
--- a/jdk/test/sun/jvmstat/testlibrary/utils.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/jvmstat/testlibrary/utils.sh Mon Sep 14 07:03:04 2015 +0000
@@ -221,5 +221,3 @@
fi
echo "${port1}"
}
-
-
--- a/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -57,5 +57,3 @@
}
}
-
-
--- a/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -61,5 +61,3 @@
test.runTest(args);
}
}
-
-
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -186,4 +186,4 @@
private Properties getCounters() throws IOException, InterruptedException {
return jcmd.perfCounters("sun\\.management\\.JMXConnectorServer\\..*");
}
-}
\ No newline at end of file
+}
--- a/jdk/test/sun/management/jmxremote/startstop/REMOTE_TESTING.txt Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/management/jmxremote/startstop/REMOTE_TESTING.txt Mon Sep 14 07:03:04 2015 +0000
@@ -15,5 +15,3 @@
6. connect jconsole to host2:50234
Make sure jconsole works
Make sure only host2.50234 and host2.50235 appears in tcpdump output.
-
-
--- a/jdk/test/sun/management/windows/README Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/management/windows/README Mon Sep 14 07:03:04 2015 +0000
@@ -26,5 +26,3 @@
Note that a 32-bit version of revokeall.exe is checked into SCCS
- this 32-bit application is also used when running on 64-bit
versions of Windows (AMD64 and IA64).
-
-
--- a/jdk/test/sun/net/www/http/HttpClient/IsKeepingAlive.policy Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/net/www/http/HttpClient/IsKeepingAlive.policy Mon Sep 14 07:03:04 2015 +0000
@@ -45,5 +45,3 @@
permission java.util.PropertyPermission "java.vm.vendor", "read";
permission java.util.PropertyPermission "java.vm.name", "read";
};
-
-
--- a/jdk/test/sun/net/www/http/HttpClient/OpenServer.policy Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/net/www/http/HttpClient/OpenServer.policy Mon Sep 14 07:03:04 2015 +0000
@@ -45,5 +45,3 @@
permission java.util.PropertyPermission "java.vm.vendor", "read";
permission java.util.PropertyPermission "java.vm.name", "read";
};
-
-
--- a/jdk/test/sun/net/www/protocol/http/spnegoTest Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/net/www/protocol/http/spnegoTest Mon Sep 14 07:03:04 2015 +0000
@@ -205,4 +205,4 @@
rm err.log
rm out.log
-exit 0
\ No newline at end of file
+exit 0
--- a/jdk/test/sun/security/ec/SignatureOffsets.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/ec/SignatureOffsets.java Mon Sep 14 07:03:04 2015 +0000
@@ -49,4 +49,4 @@
InvalidKeyException, SignatureException {
Offsets.main(args);
}
-}
\ No newline at end of file
+}
--- a/jdk/test/sun/security/krb5/IPv6.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/krb5/IPv6.java Mon Sep 14 07:03:04 2015 +0000
@@ -127,5 +127,3 @@
}
}
}
-
-
--- a/jdk/test/sun/security/mscapi/KeytoolChangeAlias.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/mscapi/KeytoolChangeAlias.sh Mon Sep 14 07:03:04 2015 +0000
@@ -132,6 +132,3 @@
exit 0
;;
esac
-
-
-
--- a/jdk/test/sun/security/mscapi/SignatureOffsets.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/mscapi/SignatureOffsets.java Mon Sep 14 07:03:04 2015 +0000
@@ -50,4 +50,4 @@
InvalidKeyException, SignatureException {
Offsets.main(args);
}
-}
\ No newline at end of file
+}
--- a/jdk/test/sun/security/pkcs11/Provider/Absolute.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/pkcs11/Provider/Absolute.java Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,40 +22,31 @@
*/
/**
* @test
- * @bug 7003952
+ * @bug 7003952 7191662
+ * @library ..
* @summary load DLLs and launch executables using fully qualified path
*/
import java.security.*;
-import java.lang.reflect.*;
public class Absolute {
public static void main(String[] args) throws Exception {
- Constructor cons;
- try {
- Class clazz = Class.forName("sun.security.pkcs11.SunPKCS11");
- cons = clazz.getConstructor(new Class[] {String.class});
- } catch (Exception ex) {
- System.out.println("Skipping test - no PKCS11 provider available");
- return;
- }
-
String config =
System.getProperty("test.src", ".") + "/Absolute.cfg";
try {
- Object obj = cons.newInstance(new Object[] {config});
- } catch (InvocationTargetException ite) {
- Throwable cause = ite.getCause();
- if (cause instanceof ProviderException) {
- Throwable cause2 = cause.getCause();
- if ((cause2 == null) ||
- !cause2.getMessage().startsWith(
- "Absolute path required for library value:")) {
- // rethrow
- throw (ProviderException) cause;
- }
- System.out.println("Caught expected Exception: \n" + cause2);
+ Provider p = PKCS11Test.getSunPKCS11(config);
+ if (p == null) {
+ System.out.println("Skipping test - no PKCS11 provider available");
+ }
+ } catch (InvalidParameterException ipe) {
+ Throwable ex = ipe.getCause();
+ if (ex.getMessage().indexOf(
+ "Absolute path required for library value:") != -1) {
+ System.out.println("Test Passed: expected exception thrown");
+ } else {
+ // rethrow
+ throw ipe;
}
}
}
--- a/jdk/test/sun/security/pkcs11/Provider/ConfigShortPath.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/pkcs11/Provider/ConfigShortPath.java Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,44 +33,52 @@
public class ConfigShortPath {
- private static final String[] configNames = {
- "csp.cfg", "cspPlus.cfg", "cspSpace.cfg", "cspQuotedPath.cfg"
+ private static final String[] winConfigNames = {
+ "csp.cfg", "cspSpace.cfg", "cspQuotedPath.cfg"
+ };
+ private static final String[] solConfigNames = {
+ "cspPlus.cfg"
};
public static void main(String[] args) throws Exception {
- Constructor cons = null;
- try {
- Class clazz = Class.forName("sun.security.pkcs11.SunPKCS11");
- cons = clazz.getConstructor(String.class);
- } catch (Exception ex) {
- System.out.println("Skipping test - no PKCS11 provider available");
- return;
+ Provider p = Security.getProvider("SunPKCS11");
+ if (p == null) {
+ // re-try w/ SunPKCS11-Solaris
+ p = Security.getProvider("SunPKCS11-Solaris");
+ if (p == null) {
+ System.out.println("Skipping test - no PKCS11 provider available");
+ return;
+ }
}
+
+ String osInfo = System.getProperty("os.name", "");
+ String[] configNames = (osInfo.contains("Windows")?
+ winConfigNames : solConfigNames);
+
String testSrc = System.getProperty("test.src", ".");
for (int i = 0; i < configNames.length; i++) {
String configFile = testSrc + File.separator + configNames[i];
System.out.println("Testing against " + configFile);
try {
- Object obj = cons.newInstance(configFile);
- } catch (InvocationTargetException ite) {
- Throwable cause = ite.getCause();
- System.out.println(cause);
- if (cause instanceof ProviderException) {
- while ((cause = cause.getCause()) != null) {
- System.out.println(cause);
- String causeMsg = cause.getMessage();
- // Indicate failure if due to parsing config
- if (causeMsg.indexOf("Unexpected") != -1) {
- throw (ProviderException) cause;
- }
+ p.configure(configFile);
+ } catch (InvalidParameterException ipe) {
+ ipe.printStackTrace();
+ Throwable cause = ipe.getCause();
+ // Indicate failure if due to parsing config
+ if (cause.getClass().getName().equals
+ ("sun.security.pkcs11.ConfigurationException")) {
+ // Error occurred during parsing
+ if (cause.getMessage().indexOf("Unexpected") != -1) {
+ throw (ProviderException) cause;
}
- // Consider the test passes if the exception is
- // thrown after parsing, i.e. due to the absolute
- // path requirement or the non-existent path.
- } else {
- // unexpected exception
- throw new RuntimeException("Unexpected Exception", cause);
+ }
+ } catch (ProviderException pe) {
+ pe.printStackTrace();
+ if (pe.getCause() instanceof IOException) {
+ // Thrown when the directory does not exist which is ok
+ System.out.println("Pass: config parsed ok");
+ continue;
}
}
}
--- a/jdk/test/sun/security/pkcs11/Provider/cspSpace.cfg Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/pkcs11/Provider/cspSpace.cfg Mon Sep 14 07:03:04 2015 +0000
@@ -1,5 +1,3 @@
showInfo = false
name = test
library = C:\pki DLL\x64\acpkcs211.dll
-
-
--- a/jdk/test/sun/security/rsa/SignatureOffsets.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/rsa/SignatureOffsets.java Mon Sep 14 07:03:04 2015 +0000
@@ -50,4 +50,4 @@
InvalidKeyException, SignatureException {
Offsets.main(args);
}
-}
\ No newline at end of file
+}
--- a/jdk/test/sun/security/ssl/StatusStapling/TestCase.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/ssl/StatusStapling/TestCase.java Mon Sep 14 07:03:04 2015 +0000
@@ -28,5 +28,3 @@
public interface TestCase {
Map.Entry<Boolean, String> runTest();
}
-
-
--- a/jdk/test/sun/security/ssl/StatusStapling/TestUtils.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/ssl/StatusStapling/TestUtils.java Mon Sep 14 07:03:04 2015 +0000
@@ -122,5 +122,3 @@
return resultBuf;
}
}
-
-
--- a/jdk/test/sun/security/ssl/rsa/SignatureOffsets.java Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/ssl/rsa/SignatureOffsets.java Mon Sep 14 07:03:04 2015 +0000
@@ -47,4 +47,4 @@
InvalidKeyException, SignatureException {
Offsets.main(args);
}
-}
\ No newline at end of file
+}
--- a/jdk/test/sun/security/tools/jarsigner/collator.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/tools/jarsigner/collator.sh Mon Sep 14 07:03:04 2015 +0000
@@ -72,5 +72,3 @@
echo "ERR is $ERR"
exit 1
fi
-
-
--- a/jdk/test/sun/security/tools/jarsigner/jvindex.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/tools/jarsigner/jvindex.sh Mon Sep 14 07:03:04 2015 +0000
@@ -72,5 +72,3 @@
echo "ERR is $ERR"
exit 1
fi
-
-
--- a/jdk/test/sun/security/tools/jarsigner/warnings.sh Mon Sep 14 07:02:50 2015 +0200
+++ b/jdk/test/sun/security/tools/jarsigner/warnings.sh Mon Sep 14 07:03:04 2015 +0000
@@ -115,5 +115,3 @@
echo "ERR is $ERR"
exit 1
fi
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/x509/X509CertImpl/V3Certificate.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import static java.lang.System.out;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import sun.misc.BASE64Encoder;
+import sun.security.util.BitArray;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.*;
+
+/**
+ * @test
+ * @bug 8049237
+ * @modules java.base/sun.security.x509
+ * java.base/sun.security.util
+ * java.base/sun.misc
+ * @summary This test generates V3 certificate with all the supported
+ * extensions. Writes back the generated certificate in to a file and checks for
+ * equality with the original certificate.
+ */
+public class V3Certificate {
+
+ public static final String V3_FILE = "certV3";
+ public static final String V3_B64_FILE = "certV3.b64";
+
+ public static void main(String[] args) throws IOException,
+ NoSuchAlgorithmException, InvalidKeyException, CertificateException,
+ NoSuchProviderException, SignatureException {
+
+ boolean success = true;
+
+ success &= test("RSA", "SHA256withRSA", 2048);
+ success &= test("DSA", "SHA256withDSA", 2048);
+ success &= test("EC", "SHA256withECDSA", 384);
+
+ if (!success) {
+ throw new RuntimeException("At least one test case failed");
+ }
+ }
+
+ public static boolean test(String algorithm, String sigAlg, int keyLength)
+ throws IOException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ CertificateException,
+ NoSuchProviderException,
+ SignatureException {
+
+ byte[] issuerId = {1, 2, 3, 4, 5};
+ byte[] subjectId = {6, 7, 8, 9, 10};
+ boolean testResult = true;
+
+ // Subject and Issuer
+ X500Name subject = new X500Name("test", "Oracle", "Santa Clara",
+ "US");
+ X500Name issuer = subject;
+
+ // Generate keys and sign
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm);
+ keyGen.initialize(keyLength);
+ KeyPair pair = keyGen.generateKeyPair();
+ PublicKey publicKey = pair.getPublic();
+ PrivateKey privateKey = pair.getPrivate();
+ MessageDigest md = MessageDigest.getInstance("SHA");
+ byte[] keyId = md.digest(publicKey.getEncoded());
+
+ Signature signature = Signature.getInstance(sigAlg);
+ signature.initSign(privateKey);
+
+ // Validity interval
+ Date firstDate = new Date();
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST"));
+ cal.set(2014, 03, 10, 12, 30, 30);
+ Date lastDate = cal.getTime();
+ CertificateValidity interval = new CertificateValidity(firstDate,
+ lastDate);
+
+ // Certificate Info
+ X509CertInfo cert = new X509CertInfo();
+
+ cert.set(X509CertInfo.VERSION,
+ new CertificateVersion(CertificateVersion.V3));
+ cert.set(X509CertInfo.SERIAL_NUMBER,
+ new CertificateSerialNumber((int) (firstDate.getTime() / 1000)));
+ cert.set(X509CertInfo.ALGORITHM_ID,
+ new CertificateAlgorithmId(AlgorithmId.get(sigAlg)));
+ cert.set(X509CertInfo.SUBJECT, subject);
+ cert.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
+ cert.set(X509CertInfo.VALIDITY, interval);
+ cert.set(X509CertInfo.ISSUER, issuer);
+
+ cert.set(X509CertInfo.ISSUER_ID,
+ new UniqueIdentity(
+ new BitArray(issuerId.length * 8 - 2, issuerId)));
+ cert.set(X509CertInfo.SUBJECT_ID, new UniqueIdentity(subjectId));
+
+ // Create Extensions
+ CertificateExtensions exts = new CertificateExtensions();
+
+ GeneralNameInterface mailInf = new RFC822Name("test@Oracle.com");
+ GeneralName mail = new GeneralName(mailInf);
+ GeneralNameInterface dnsInf = new DNSName("Oracle.com");
+ GeneralName dns = new GeneralName(dnsInf);
+ GeneralNameInterface uriInf = new URIName("http://www.Oracle.com");
+ GeneralName uri = new GeneralName(uriInf);
+
+ // localhost
+ byte[] address = new byte[]{127, 0, 0, 1};
+
+ GeneralNameInterface ipInf = new IPAddressName(address);
+ GeneralName ip = new GeneralName(ipInf);
+ int[] oidData = new int[]{1, 2, 3, 4};
+
+ GeneralNameInterface oidInf = new OIDName(new ObjectIdentifier(oidData));
+ GeneralName oid = new GeneralName(oidInf);
+
+ SubjectAlternativeNameExtension subjectName
+ = new SubjectAlternativeNameExtension();
+ IssuerAlternativeNameExtension issuerName
+ = new IssuerAlternativeNameExtension();
+
+ GeneralNames subjectNames
+ = (GeneralNames) subjectName.
+ get(SubjectAlternativeNameExtension.SUBJECT_NAME);
+
+ GeneralNames issuerNames
+ = (GeneralNames) issuerName.
+ get(IssuerAlternativeNameExtension.ISSUER_NAME);
+
+ subjectNames.add(mail);
+ subjectNames.add(dns);
+ subjectNames.add(uri);
+
+ issuerNames.add(ip);
+ issuerNames.add(oid);
+
+ cal.set(2000, 11, 15, 12, 30, 30);
+ lastDate = cal.getTime();
+ PrivateKeyUsageExtension pkusage
+ = new PrivateKeyUsageExtension(firstDate, lastDate);
+
+ KeyUsageExtension usage = new KeyUsageExtension();
+ usage.set(KeyUsageExtension.CRL_SIGN, true);
+ usage.set(KeyUsageExtension.DIGITAL_SIGNATURE, true);
+ usage.set(KeyUsageExtension.NON_REPUDIATION, true);
+
+ KeyIdentifier kid = new KeyIdentifier(keyId);
+ SerialNumber sn = new SerialNumber(42);
+ AuthorityKeyIdentifierExtension aki
+ = new AuthorityKeyIdentifierExtension(kid, subjectNames, sn);
+
+ SubjectKeyIdentifierExtension ski
+ = new SubjectKeyIdentifierExtension(keyId);
+
+ BasicConstraintsExtension cons
+ = new BasicConstraintsExtension(true, 10);
+
+ PolicyConstraintsExtension pce = new PolicyConstraintsExtension(2, 4);
+
+ exts.set(SubjectAlternativeNameExtension.NAME, subjectName);
+ exts.set(IssuerAlternativeNameExtension.NAME, issuerName);
+ exts.set(PrivateKeyUsageExtension.NAME, pkusage);
+ exts.set(KeyUsageExtension.NAME, usage);
+ exts.set(AuthorityKeyIdentifierExtension.NAME, aki);
+ exts.set(SubjectKeyIdentifierExtension.NAME, ski);
+ exts.set(BasicConstraintsExtension.NAME, cons);
+ exts.set(PolicyConstraintsExtension.NAME, pce);
+ cert.set(X509CertInfo.EXTENSIONS, exts);
+
+ // Generate and sign X509CertImpl
+ X509CertImpl crt = new X509CertImpl(cert);
+ crt.sign(privateKey, sigAlg);
+ crt.verify(publicKey);
+
+ try (FileOutputStream fos = new FileOutputStream(new File(V3_FILE));
+ FileOutputStream fos_b64
+ = new FileOutputStream(new File(V3_B64_FILE));
+ PrintWriter pw = new PrintWriter(fos_b64)) {
+ crt.encode((OutputStream) fos);
+ fos.flush();
+
+ // Certificate boundaries/
+ pw.println("-----BEGIN CERTIFICATE-----");
+ pw.flush();
+ new BASE64Encoder().encodeBuffer(crt.getEncoded(), fos_b64);
+ fos_b64.flush();
+ pw.println("-----END CERTIFICATE-----");
+ }
+
+ out.println("*** Certificate ***");
+ out.println(crt);
+ out.println("*** End Certificate ***");
+
+ X509Certificate x2 = generateCertificate(V3_FILE);
+ if (!x2.equals(crt)) {
+ out.println("*** Certificate mismatch ***");
+ testResult = false;
+ }
+
+ X509Certificate x3 = generateCertificate(V3_B64_FILE);
+ if (!x3.equals(crt)) {
+ out.println("*** Certificate mismatch ***");
+ testResult = false;
+ }
+
+ return testResult;
+ }
+
+ static X509Certificate generateCertificate(String certFile) {
+ try (InputStream inStrm = new FileInputStream(certFile)) {
+ CertificateFactory cf = CertificateFactory.getInstance("X509");
+ X509Certificate x2
+ = (X509Certificate) cf.generateCertificate(inStrm);
+ return x2;
+ } catch (CertificateException | IOException e) {
+ throw new RuntimeException("Exception while "
+ + "genrating certificate for " + certFile, e);
+ }
+ }
+}
--- a/langtools/.hgtags Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/.hgtags Mon Sep 14 07:03:04 2015 +0000
@@ -322,3 +322,4 @@
6ec3d5cb1bfcfba135c8d18866e567f1b1ada861 jdk9-b77
7fd155b7041c8aba7084f03e2fd1d6f74cceda75 jdk9-b78
eaab8a16dcfb807acacdb6d133f3ecd502667a8c jdk9-b79
+c5671e662392df372b2005b75afa6cfdc0eebce7 jdk9-b80
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Mon Sep 14 07:03:04 2015 +0000
@@ -76,7 +76,7 @@
private final AtomicBoolean used = new AtomicBoolean();
private Iterable<? extends Processor> processors;
- JavacTaskImpl(Context context) {
+ protected JavacTaskImpl(Context context) {
super(context, true);
args = Arguments.instance(context);
fileManager = context.get(JavaFileManager.class);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/MultiTaskListener.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/MultiTaskListener.java Mon Sep 14 07:03:04 2015 +0000
@@ -47,6 +47,9 @@
/** The context key for the MultiTaskListener. */
public static final Context.Key<MultiTaskListener> taskListenerKey = new Context.Key<>();
+ /** Empty array of task listeners */
+ private static final TaskListener[] EMPTY_LISTENERS = new TaskListener[0];
+
/** Get the MultiTaskListener instance for this context. */
public static MultiTaskListener instance(Context context) {
MultiTaskListener instance = context.get(taskListenerKey);
@@ -64,7 +67,7 @@
* The current set of registered listeners.
* This is a mutable reference to an immutable array.
*/
- TaskListener[] listeners = { };
+ TaskListener[] listeners = EMPTY_LISTENERS;
ClientCodeWrapper ccw;
@@ -73,7 +76,7 @@
}
public boolean isEmpty() {
- return (listeners.length == 0);
+ return listeners == EMPTY_LISTENERS;
}
public void add(TaskListener listener) {
@@ -88,10 +91,14 @@
public void remove(TaskListener listener) {
for (int i = 0; i < listeners.length; i++) {
if (ccw.unwrap(listeners[i]) == listener) {
- TaskListener[] newListeners = new TaskListener[listeners.length - 1];
- System.arraycopy(listeners, 0, newListeners, 0, i);
- System.arraycopy(listeners, i + 1, newListeners, i, newListeners.length - i);
- listeners = newListeners;
+ if (listeners.length == 1) {
+ listeners = EMPTY_LISTENERS;
+ } else {
+ TaskListener[] newListeners = new TaskListener[listeners.length - 1];
+ System.arraycopy(listeners, 0, newListeners, 0, i);
+ System.arraycopy(listeners, i + 1, newListeners, i, newListeners.length - i);
+ listeners = newListeners;
+ }
break;
}
}
@@ -117,4 +124,8 @@
public String toString() {
return Arrays.toString(listeners);
}
+
+ public void clear() {
+ listeners = EMPTY_LISTENERS;
+ }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Mon Sep 14 07:03:04 2015 +0000
@@ -26,6 +26,7 @@
package com.sun.tools.javac.code;
import com.sun.tools.javac.code.Kinds.Kind;
+import java.lang.ref.WeakReference;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
@@ -162,15 +163,49 @@
/** A list of scopes to be notified if items are to be removed from this scope.
*/
- List<ScopeListener> listeners = List.nil();
+ ScopeListenerList listeners = new ScopeListenerList();
- public void addScopeListener(ScopeListener sl) {
- listeners = listeners.prepend(sl);
+ public interface ScopeListener {
+ void symbolAdded(Symbol sym, Scope s);
+ void symbolRemoved(Symbol sym, Scope s);
}
- public interface ScopeListener {
- public void symbolAdded(Symbol sym, Scope s);
- public void symbolRemoved(Symbol sym, Scope s);
+ /**
+ * A list of scope listeners; listeners are stored in weak references, to avoid memory leaks.
+ * When the listener list is scanned (upon notification), elements corresponding to GC-ed
+ * listeners are removed so that the listener list size is kept in check.
+ */
+ public static class ScopeListenerList {
+
+ List<WeakReference<ScopeListener>> listeners = List.nil();
+
+ void add(ScopeListener sl) {
+ listeners = listeners.prepend(new WeakReference<>(sl));
+ }
+
+ void symbolAdded(Symbol sym, Scope scope) {
+ walkReferences(sym, scope, false);
+ }
+
+ void symbolRemoved(Symbol sym, Scope scope) {
+ walkReferences(sym, scope, true);
+ }
+
+ private void walkReferences(Symbol sym, Scope scope, boolean isRemove) {
+ ListBuffer<WeakReference<ScopeListener>> newListeners = new ListBuffer<>();
+ for (WeakReference<ScopeListener> wsl : listeners) {
+ ScopeListener sl = wsl.get();
+ if (sl != null) {
+ if (isRemove) {
+ sl.symbolRemoved(sym, scope);
+ } else {
+ sl.symbolAdded(sym, scope);
+ }
+ newListeners.add(wsl);
+ }
+ }
+ listeners = newListeners.toList();
+ }
}
public enum LookupKind {
@@ -404,9 +439,7 @@
elems = e;
//notify listeners
- for (List<ScopeListener> l = listeners; l.nonEmpty(); l = l.tail) {
- l.head.symbolAdded(sym, this);
- }
+ listeners.symbolAdded(sym, this);
}
/** Remove symbol from this scope.
@@ -442,9 +475,7 @@
}
//notify listeners
- for (List<ScopeListener> l = listeners; l.nonEmpty(); l = l.tail) {
- l.head.symbolRemoved(sym, this);
- }
+ listeners.symbolRemoved(sym, this);
}
/** Enter symbol sym in this scope if not already there.
@@ -698,11 +729,12 @@
finalized.enter(sym);
}
- finalized.addScopeListener(new ScopeListener() {
+ finalized.listeners.add(new ScopeListener() {
@Override
public void symbolAdded(Symbol sym, Scope s) {
Assert.error("The scope is sealed.");
}
+
@Override
public void symbolRemoved(Symbol sym, Scope s) {
Assert.error("The scope is sealed.");
@@ -929,26 +961,20 @@
public void prependSubScope(Scope that) {
if (that != null) {
subScopes = subScopes.prepend(that);
- that.addScopeListener(this);
+ that.listeners.add(this);
mark++;
- for (ScopeListener sl : listeners) {
- sl.symbolAdded(null, this); //propagate upwards in case of nested CompoundScopes
- }
+ listeners.symbolAdded(null, this);
}
}
public void symbolAdded(Symbol sym, Scope s) {
mark++;
- for (ScopeListener sl : listeners) {
- sl.symbolAdded(sym, s);
- }
+ listeners.symbolAdded(sym, s);
}
public void symbolRemoved(Symbol sym, Scope s) {
mark++;
- for (ScopeListener sl : listeners) {
- sl.symbolRemoved(sym, s);
- }
+ listeners.symbolRemoved(sym, s);
}
public int getMark() {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Mon Sep 14 07:03:04 2015 +0000
@@ -68,7 +68,7 @@
/**
* The context key for the arguments.
*/
- protected static final Context.Key<Arguments> argsKey = new Context.Key<>();
+ public static final Context.Key<Arguments> argsKey = new Context.Key<>();
private String ownName;
private Set<String> classNames;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Sep 14 07:03:04 2015 +0000
@@ -87,7 +87,7 @@
*/
public class JavaCompiler {
/** The context key for the compiler. */
- protected static final Context.Key<JavaCompiler> compilerKey = new Context.Key<>();
+ public static final Context.Key<JavaCompiler> compilerKey = new Context.Key<>();
/** Get the JavaCompiler instance for this context. */
public static JavaCompiler instance(Context context) {
@@ -821,7 +821,7 @@
// as a JavaCompiler can only be used once, throw an exception if
// it has been used before.
if (hasBeenUsed)
- throw new AssertionError("attempt to reuse JavaCompiler");
+ checkReusable();
hasBeenUsed = true;
// forcibly set the equivalent of -Xlint:-options, so that no further
@@ -898,6 +898,10 @@
}
}
+ protected void checkReusable() {
+ throw new AssertionError("attempt to reuse JavaCompiler");
+ }
+
/**
* Set needRootClasses to true, in JavaCompiler subclass constructor
* that want to collect public apis of classes supplied on the command line.
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Sep 14 07:03:04 2015 +0000
@@ -26,6 +26,7 @@
package com.sun.tools.javac.parser;
import java.util.*;
+import java.util.stream.Collectors;
import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
@@ -510,7 +511,7 @@
if (mods != 0) {
long lowestMod = mods & -mods;
error(token.pos, "mod.not.allowed.here",
- Flags.asFlagSet(lowestMod));
+ Flags.asFlagSet(lowestMod));
}
}
@@ -946,10 +947,7 @@
t = odStack[0];
if (t.hasTag(JCTree.Tag.PLUS)) {
- StringBuilder buf = foldStrings(t);
- if (buf != null) {
- t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
- }
+ t = foldStrings(t);
}
odStackSupply.add(odStack);
@@ -973,37 +971,76 @@
/** If tree is a concatenation of string literals, replace it
* by a single literal representing the concatenated string.
*/
- protected StringBuilder foldStrings(JCTree tree) {
+ protected JCExpression foldStrings(JCExpression tree) {
if (!allowStringFolding)
return null;
- List<String> buf = List.nil();
+ ListBuffer<JCExpression> opStack = new ListBuffer<>();
+ ListBuffer<JCLiteral> litBuf = new ListBuffer<>();
+ boolean needsFolding = false;
+ JCExpression curr = tree;
while (true) {
- if (tree.hasTag(LITERAL)) {
- JCLiteral lit = (JCLiteral) tree;
- if (lit.typetag == TypeTag.CLASS) {
- StringBuilder sbuf =
- new StringBuilder((String)lit.value);
- while (buf.nonEmpty()) {
- sbuf.append(buf.head);
- buf = buf.tail;
- }
- return sbuf;
- }
- } else if (tree.hasTag(JCTree.Tag.PLUS)) {
- JCBinary op = (JCBinary)tree;
- if (op.rhs.hasTag(LITERAL)) {
- JCLiteral lit = (JCLiteral) op.rhs;
- if (lit.typetag == TypeTag.CLASS) {
- buf = buf.prepend((String) lit.value);
- tree = op.lhs;
- continue;
- }
- }
+ if (curr.hasTag(JCTree.Tag.PLUS)) {
+ JCBinary op = (JCBinary)curr;
+ needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false);
+ curr = op.lhs;
+ } else {
+ needsFolding |= foldIfNeeded(curr, litBuf, opStack, true);
+ break; //last one!
}
- return null;
+ }
+ if (needsFolding) {
+ List<JCExpression> ops = opStack.toList();
+ JCExpression res = ops.head;
+ for (JCExpression op : ops.tail) {
+ res = F.at(op.getStartPosition()).Binary(optag(TokenKind.PLUS), res, op);
+ storeEnd(res, getEndPos(op));
+ }
+ return res;
+ } else {
+ return tree;
}
}
+ private boolean foldIfNeeded(JCExpression tree, ListBuffer<JCLiteral> litBuf,
+ ListBuffer<JCExpression> opStack, boolean last) {
+ JCLiteral str = stringLiteral(tree);
+ if (str != null) {
+ litBuf.prepend(str);
+ return last && merge(litBuf, opStack);
+ } else {
+ boolean res = merge(litBuf, opStack);
+ litBuf.clear();
+ opStack.prepend(tree);
+ return res;
+ }
+ }
+
+ boolean merge(ListBuffer<JCLiteral> litBuf, ListBuffer<JCExpression> opStack) {
+ if (litBuf.isEmpty()) {
+ return false;
+ } else if (litBuf.size() == 1) {
+ opStack.prepend(litBuf.first());
+ return false;
+ } else {
+ JCExpression t = F.at(litBuf.first().getStartPosition()).Literal(TypeTag.CLASS,
+ litBuf.stream().map(lit -> (String)lit.getValue()).collect(Collectors.joining()));
+ storeEnd(t, litBuf.last().getEndPosition(endPosTable));
+ opStack.prepend(t);
+ return true;
+ }
+ }
+
+ private JCLiteral stringLiteral(JCTree tree) {
+ if (tree.hasTag(LITERAL)) {
+ JCLiteral lit = (JCLiteral)tree;
+ if (lit.typetag == TypeTag.CLASS) {
+ return lit;
+ }
+ }
+ return null;
+ }
+
+
/** optimization: To save allocating a new operand/operator stack
* for every binary operation, we use supplys.
*/
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java Mon Sep 14 07:03:04 2015 +0000
@@ -119,7 +119,7 @@
* or
* {@literal Key<T> -> Factory<T> }
*/
- private final Map<Key<?>,Object> ht = new HashMap<>();
+ protected final Map<Key<?>,Object> ht = new HashMap<>();
/** Set the factory for the key in this context. */
public <T> void put(Key<T> key, Factory<T> fac) {
@@ -173,7 +173,7 @@
*/
private final Map<Class<?>, Key<?>> kt = new HashMap<>();
- private <T> Key<T> key(Class<T> clss) {
+ protected <T> Key<T> key(Class<T> clss) {
checkState(kt);
Key<T> k = uncheckedCast(kt.get(clss));
if (k == null) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Mon Sep 14 07:03:04 2015 +0000
@@ -334,7 +334,7 @@
* error message more than once. For each error, a pair consisting of the
* source file name and source code position of the error is added to the set.
*/
- private Set<Pair<JavaFileObject, Integer>> recorded = new HashSet<>();
+ protected Set<Pair<JavaFileObject, Integer>> recorded = new HashSet<>();
public boolean hasDiagnosticListener() {
return diagListener != null;
--- a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java Mon Sep 14 07:03:04 2015 +0000
@@ -25,26 +25,19 @@
* @test
* @bug 6769027 8006694
* @summary Source line should be displayed immediately after the first diagnostic line
- * temporarily workaround combo tests are causing time out in several platforms
- * @author Maurizio Cimadamore
- * @library ../../lib
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.util
- * @build JavacTestingAbstractThreadedTest
* @run main/othervm T6769027
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+// use /othervm to avoid locale issues
import java.net.URI;
import java.util.regex.Matcher;
import javax.tools.*;
import com.sun.tools.javac.util.*;
-public class T6769027
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+public class T6769027 {
enum OutputKind {
RAW("rawDiagnostics","rawDiagnostics"),
@@ -324,11 +317,6 @@
}
@Override
- protected java.io.PrintWriter getWriterForDiagnosticType(JCDiagnostic.DiagnosticType dt) {
- return outWriter;
- }
-
- @Override
protected boolean shouldReport(JavaFileObject jfo, int pos) {
return true;
}
@@ -368,7 +356,6 @@
this.subdiagsIndent = subdiagsIndent;
}
- @Override
public void run() {
Context ctx = new Context();
Options options = Options.instance(ctx);
@@ -419,7 +406,7 @@
for (IndentKind detailsIndent : IndentKind.values()) {
for (IndentKind sourceIndent : IndentKind.values()) {
for (IndentKind subdiagsIndent : IndentKind.values()) {
- pool.execute(new T6769027(outputKind,
+ new T6769027(outputKind,
errKind,
multiKind,
multiPolicy,
@@ -431,7 +418,7 @@
summaryIndent,
detailsIndent,
sourceIndent,
- subdiagsIndent));
+ subdiagsIndent).run();
}
}
}
@@ -445,8 +432,6 @@
}
}
}
-
- checkAfterExec(false);
}
void printInfo(String msg, String errorLine) {
@@ -457,11 +442,11 @@
" caret=" + caretKind + " sourcePosition=" + sourceLineKind +
" summaryIndent=" + summaryIndent + " detailsIndent=" + detailsIndent +
" sourceIndent=" + sourceIndent + " subdiagsIndent=" + subdiagsIndent;
- errWriter.println(sep);
- errWriter.println(desc);
- errWriter.println(sep);
- errWriter.println(msg);
- errWriter.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine);
+ System.err.println(sep);
+ System.err.println(desc);
+ System.err.println(sep);
+ System.err.println(msg);
+ System.err.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine);
}
void checkOutput(String msg) {
@@ -494,8 +479,8 @@
}
if (!msg.equals(errorLine)) {
-// printInfo(msg, errorLine);
- errCount.incrementAndGet();
+ printInfo(msg, errorLine);
+ throw new AssertionError("errors were found");
}
}
--- a/langtools/test/tools/javac/T7093325.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/T7093325.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,38 +23,41 @@
/*
* @test
- * @bug 7093325 8006694
+ * @bug 7093325 8006694 8129962
* @summary Redundant entry in bytecode exception table
* temporarily workaround combo tests are causing time out in several platforms
- * @library lib
+ * @library /tools/javac/lib
* @modules jdk.jdeps/com.sun.tools.classfile
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm T7093325
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main T7093325
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import java.io.IOException;
+import java.io.InputStream;
-import java.io.File;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.ToolProvider;
-
-import com.sun.source.util.JavacTask;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.Code_attribute;
-import com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Method;
-public class T7093325
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+import javax.tools.JavaFileObject;
- enum StatementKind {
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
+
+public class T7093325 extends ComboInstance<T7093325> {
+
+ enum StatementKind implements ComboParameter {
+ NONE(null, false, false),
THROW("throw new RuntimeException();", false, false),
RETURN_NONEMPTY("System.out.println(); return;", true, false),
RETURN_EMPTY("return;", true, true),
@@ -64,107 +67,79 @@
boolean canInline;
boolean empty;
- private StatementKind(String stmt, boolean canInline, boolean empty) {
+ StatementKind(String stmt, boolean canInline, boolean empty) {
this.stmt = stmt;
this.canInline = canInline;
this.empty = empty;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return stmt;
+ }
}
- enum CatchArity {
+ enum CatchArity implements ComboParameter {
NONE(""),
- ONE("catch (A a) { #S1 }"),
- TWO("catch (B b) { #S2 }"),
- THREE("catch (C c) { #S3 }"),
- FOUR("catch (D d) { #S4 }");
+ ONE("catch (A a) { #{STMT[1]} }"),
+ TWO("catch (B b) { #{STMT[2]} }"),
+ THREE("catch (C c) { #{STMT[3]} }"),
+ FOUR("catch (D d) { #{STMT[4]} }");
String catchStr;
- private CatchArity(String catchStr) {
+ CatchArity(String catchStr) {
this.catchStr = catchStr;
}
- String catchers() {
+ @Override
+ public String expand(String optParameter) {
if (this.ordinal() == 0) {
return catchStr;
} else {
- return CatchArity.values()[this.ordinal() - 1].catchers() +
+ return CatchArity.values()[this.ordinal() - 1].expand(optParameter) +
catchStr;
}
}
}
public static void main(String... args) throws Exception {
- for (CatchArity ca : CatchArity.values()) {
- for (StatementKind stmt0 : StatementKind.values()) {
- if (ca.ordinal() == 0) {
- pool.execute(new T7093325(ca, stmt0));
- continue;
- }
- for (StatementKind stmt1 : StatementKind.values()) {
- if (ca.ordinal() == 1) {
- pool.execute(new T7093325(ca, stmt0, stmt1));
- continue;
- }
- for (StatementKind stmt2 : StatementKind.values()) {
- if (ca.ordinal() == 2) {
- pool.execute(new T7093325(ca, stmt0, stmt1, stmt2));
- continue;
- }
- for (StatementKind stmt3 : StatementKind.values()) {
- if (ca.ordinal() == 3) {
- pool.execute(
- new T7093325(ca, stmt0, stmt1, stmt2, stmt3));
- continue;
- }
- for (StatementKind stmt4 : StatementKind.values()) {
- if (ca.ordinal() == 4) {
- pool.execute(
- new T7093325(ca, stmt0, stmt1,
- stmt2, stmt3, stmt4));
- continue;
- }
- for (StatementKind stmt5 : StatementKind.values()) {
- pool.execute(
- new T7093325(ca, stmt0, stmt1, stmt2,
- stmt3, stmt4, stmt5));
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
+ new ComboTestHelper<T7093325>()
+ .withFilter(T7093325::testFilter)
+ .withDimension("CATCH", (x, ca) -> x.ca = ca, CatchArity.values())
+ .withArrayDimension("STMT", (x, stmt, idx) -> x.stmts[idx] = stmt, 5, StatementKind.values())
+ .run(T7093325::new);
}
/** instance decls **/
CatchArity ca;
- StatementKind[] stmts;
+ StatementKind[] stmts = new StatementKind[5];
- public T7093325(CatchArity ca, StatementKind... stmts) {
- this.ca = ca;
- this.stmts = stmts;
+ boolean testFilter() {
+ int lastPos = ca.ordinal() + 1;
+ for (int i = 0; i < stmts.length ; i++) {
+ boolean shouldBeSet = i < lastPos;
+ boolean isSet = stmts[i] != StatementKind.NONE;
+ if (shouldBeSet != isSet) {
+ return false;
+ }
+ }
+ return true;
}
@Override
- public void run() {
- int id = checkCount.incrementAndGet();
- final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
- JavaSource source = new JavaSource(id);
- JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), null,
- null, null, Arrays.asList(source));
- ct.call();
- verifyBytecode(source, id);
+ public void doWork() throws IOException {
+ verifyBytecode(newCompilationTask()
+ .withSourceFromTemplate(source_template)
+ .generate());
}
- void verifyBytecode(JavaSource source, int id) {
+ void verifyBytecode(Result<Iterable<? extends JavaFileObject>> result) {
boolean lastInlined = false;
boolean hasCode = false;
int gapsCount = 0;
- for (int i = 0; i < stmts.length ; i++) {
+ for (int i = 0; i < ca.ordinal() + 1 ; i++) {
lastInlined = stmts[i].canInline;
hasCode = hasCode || !stmts[i].empty;
if (lastInlined && hasCode) {
@@ -176,12 +151,11 @@
gapsCount++;
}
- File compiledTest = new File(String.format("Test%s.class", id));
- try {
- ClassFile cf = ClassFile.read(compiledTest);
+ try (InputStream is = result.get().iterator().next().openInputStream()) {
+ ClassFile cf = ClassFile.read(is);
if (cf == null) {
- throw new Error("Classfile not found: " +
- compiledTest.getName());
+ fail("Classfile not found: " + result.compilationInfo());
+ return;
}
Method test_method = null;
@@ -193,7 +167,8 @@
}
if (test_method == null) {
- throw new Error("Method test() not found in class Test");
+ fail("Method test() not found in class Test" + result.compilationInfo());
+ return;
}
Code_attribute code = null;
@@ -205,7 +180,8 @@
}
if (code == null) {
- throw new Error("Code attribute not found in method test()");
+ fail("Code attribute not found in method test()");
+ return;
}
int actualGapsCount = 0;
@@ -217,54 +193,28 @@
}
if (actualGapsCount != gapsCount) {
- throw new Error("Bad exception table for test()\n" +
+ fail("Bad exception table for test()\n" +
"expected gaps: " + gapsCount + "\n" +
"found gaps: " + actualGapsCount + "\n" +
- source);
+ result.compilationInfo());
+ return;
}
- } catch (Exception e) {
+ } catch (IOException | ConstantPoolException e) {
e.printStackTrace();
- throw new Error("error reading " + compiledTest +": " + e);
+ fail("error reading classfile: " + e);
}
}
- class JavaSource extends SimpleJavaFileObject {
-
- static final String source_template =
+ static final String source_template =
+ "class Test {\n" +
+ " void test() {\n" +
+ " try { #{STMT[0]} } #{CATCH} finally { System.out.println(); }\n" +
+ " }\n" +
+ "}\n" +
"class A extends RuntimeException {} \n" +
"class B extends RuntimeException {} \n" +
"class C extends RuntimeException {} \n" +
"class D extends RuntimeException {} \n" +
- "class E extends RuntimeException {} \n" +
- "class Test#ID {\n" +
- " void test() {\n" +
- " try { #S0 } #C finally { System.out.println(); }\n" +
- " }\n" +
- "}";
-
- String source;
-
- public JavaSource(int id) {
- super(URI.create(String.format("myfo:/Test%s.java", id)),
- JavaFileObject.Kind.SOURCE);
- source = source_template.replace("#C", ca.catchers());
- source = source.replace("#S0", stmts[0].stmt);
- source = source.replace("#ID", String.valueOf(id));
- for (int i = 1; i < ca.ordinal() + 1; i++) {
- source = source.replace("#S" + i, stmts[i].stmt);
- }
- }
-
- @Override
- public String toString() {
- return source;
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
- }
-
+ "class E extends RuntimeException {}";
}
--- a/langtools/test/tools/javac/TestBootstrapMethodsCount.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * @test
- * @bug 8129547
- * @summary Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs
- * @library lib
- * @modules jdk.jdeps/com.sun.tools.classfile
- * jdk.compiler/com.sun.tools.javac.api
- * jdk.compiler/com.sun.tools.javac.code
- * jdk.compiler/com.sun.tools.javac.jvm
- * jdk.compiler/com.sun.tools.javac.tree
- * jdk.compiler/com.sun.tools.javac.util
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm TestBootstrapMethodsCount
- */
-
-import java.io.File;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Locale;
-
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-
-import com.sun.source.tree.MethodInvocationTree;
-import com.sun.source.tree.MethodTree;
-import com.sun.source.util.TaskEvent;
-import com.sun.source.util.TaskListener;
-import com.sun.source.util.TreeScanner;
-
-import com.sun.tools.classfile.Attribute;
-import com.sun.tools.classfile.BootstrapMethods_attribute;
-import com.sun.tools.classfile.ClassFile;
-
-import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
-import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
-import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
-import com.sun.tools.javac.tree.JCTree.JCIdent;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Names;
-
-import static com.sun.tools.javac.jvm.ClassFile.*;
-
-public class TestBootstrapMethodsCount
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
-
-
- public static void main(String... args) throws Exception {
- pool.execute(new TestBootstrapMethodsCount());
- checkAfterExec();
- }
-
- DiagChecker dc;
-
- TestBootstrapMethodsCount() {
- dc = new DiagChecker();
- }
-
- public void run() {
- int id = checkCount.incrementAndGet();
- JavaSource source = new JavaSource(id);
- JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc,
- Arrays.asList("-g"), null, Arrays.asList(source));
- Context context = ct.getContext();
- Symtab syms = Symtab.instance(context);
- Names names = Names.instance(context);
- Types types = Types.instance(context);
- ct.addTaskListener(new Indifier(syms, names, types));
- try {
- ct.generate();
- } catch (Throwable t) {
- t.printStackTrace();
- throw new AssertionError(
- String.format("Error thrown when compiling following code\n%s",
- source.source));
- }
- if (dc.diagFound) {
- throw new AssertionError(
- String.format("Diags found when compiling following code\n%s\n\n%s",
- source.source, dc.printDiags()));
- }
- verifyBytecode(id);
- }
-
- void verifyBytecode(int id) {
- File compiledTest = new File(String.format("Test%d.class", id));
- try {
- ClassFile cf = ClassFile.read(compiledTest);
- BootstrapMethods_attribute bsm_attr =
- (BootstrapMethods_attribute)cf
- .getAttribute(Attribute.BootstrapMethods);
- int length = bsm_attr.bootstrap_method_specifiers.length;
- if (length != 1) {
- throw new Error("Bad number of method specifiers " +
- "in BootstrapMethods attribute: " + length);
- }
- } catch (Exception e) {
- e.printStackTrace();
- throw new Error("error reading " + compiledTest +": " + e);
- }
- }
-
- class JavaSource extends SimpleJavaFileObject {
-
- static final String source_template = "import java.lang.invoke.*;\n" +
- "class Bootstrap {\n" +
- " public static CallSite bsm(MethodHandles.Lookup lookup, " +
- "String name, MethodType methodType) {\n" +
- " return null;\n" +
- " }\n" +
- "}\n" +
- "class Test#ID {\n" +
- " void m1() { }\n" +
- " void m2(Object arg1) { }\n" +
- " void test1() {\n" +
- " Object o = this; // marker statement \n" +
- " m1();\n" +
- " }\n" +
- " void test2(Object arg1) {\n" +
- " Object o = this; // marker statement \n" +
- " m2(arg1);\n" +
- " }\n" +
- "}";
-
- String source;
-
- JavaSource(int id) {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = source_template.replace("#ID", String.valueOf(id));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
- }
-
- class Indifier extends TreeScanner<Void, Void> implements TaskListener {
-
- MethodSymbol bsm;
- Symtab syms;
- Names names;
- Types types;
-
- Indifier(Symtab syms, Names names, Types types) {
- this.syms = syms;
- this.names = names;
- this.types = types;
- }
-
- @Override
- public void started(TaskEvent e) {
- //do nothing
- }
-
- @Override
- public void finished(TaskEvent e) {
- if (e.getKind() == TaskEvent.Kind.ANALYZE) {
- scan(e.getCompilationUnit(), null);
- }
- }
-
- @Override
- public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
- super.visitMethodInvocation(node, p);
- JCMethodInvocation apply = (JCMethodInvocation)node;
- JCIdent ident = (JCIdent)apply.meth;
- Symbol oldSym = ident.sym;
- if (!oldSym.isConstructor()) {
- ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
- oldSym.owner, REF_invokeStatic, bsm, oldSym.type, new Object[0]);
- }
- return null;
- }
-
- @Override
- public Void visitMethod(MethodTree node, Void p) {
- super.visitMethod(node, p);
- if (node.getName().toString().equals("bsm")) {
- bsm = ((JCMethodDecl)node).sym;
- }
- return null;
- }
- }
-
- static class DiagChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean diagFound;
- ArrayList<String> diags = new ArrayList<>();
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- diags.add(diagnostic.getMessage(Locale.getDefault()));
- diagFound = true;
- }
-
- String printDiags() {
- StringBuilder buf = new StringBuilder();
- for (String s : diags) {
- buf.append(s);
- buf.append("\n");
- }
- return buf.toString();
- }
- }
-
-}
--- a/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,53 +23,47 @@
/*
* @test
- * @bug 8002099 8006694
+ * @bug 8002099 8006694 8129962
* @summary Add support for intersection types in cast expression
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../../lib
- * @modules jdk.compiler/com.sun.tools.javac.util
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm/timeout=360 IntersectionTypeCastTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+
+ * @run main IntersectionTypeCastTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import com.sun.tools.javac.util.List;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.ToolProvider;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
-import com.sun.source.util.JavacTask;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
+import java.io.IOException;
-public class IntersectionTypeCastTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+public class IntersectionTypeCastTest extends ComboInstance<IntersectionTypeCastTest> {
- interface Type {
+ interface Type extends ComboParameter {
boolean subtypeOf(Type that);
- String asString();
boolean isClass();
boolean isInterface();
}
enum InterfaceKind implements Type {
- A("interface A { }\n", "A", null),
- B("interface B { }\n", "B", null),
- C("interface C extends A { }\n", "C", A);
+ A("A", null),
+ B("B", null),
+ C("C", A);
- String declStr;
String typeStr;
InterfaceKind superInterface;
- InterfaceKind(String declStr, String typeStr,
- InterfaceKind superInterface) {
- this.declStr = declStr;
+ InterfaceKind(String typeStr, InterfaceKind superInterface) {
this.typeStr = typeStr;
this.superInterface = superInterface;
}
@@ -81,11 +75,6 @@
}
@Override
- public String asString() {
- return typeStr;
- }
-
- @Override
public boolean isClass() {
return false;
}
@@ -94,42 +83,31 @@
public boolean isInterface() {
return true;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return typeStr;
+ }
}
enum ClassKind implements Type {
- OBJECT(null, "Object"),
- CA("#M class CA implements A { }\n", "CA",
- InterfaceKind.A),
- CB("#M class CB implements B { }\n", "CB",
- InterfaceKind.B),
- CAB("#M class CAB implements A, B { }\n", "CAB",
- InterfaceKind.A, InterfaceKind.B),
- CC("#M class CC implements C { }\n", "CC",
- InterfaceKind.C, InterfaceKind.A),
- CCA("#M class CCA implements C, A { }\n", "CCA",
- InterfaceKind.C, InterfaceKind.A),
- CCB("#M class CCB implements C, B { }\n", "CCB",
- InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
- CCAB("#M class CCAB implements C, A, B { }\n", "CCAB",
- InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
+ OBJECT("Object"),
+ CA("CA", InterfaceKind.A),
+ CB("CB", InterfaceKind.B),
+ CAB("CAB", InterfaceKind.A, InterfaceKind.B),
+ CC("CC", InterfaceKind.C, InterfaceKind.A),
+ CCA("CCA", InterfaceKind.C, InterfaceKind.A),
+ CCB("CCB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
+ CCAB("CCAB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
- String declTemplate;
String typeStr;
List<InterfaceKind> superInterfaces;
- ClassKind(String declTemplate, String typeStr,
- InterfaceKind... superInterfaces) {
- this.declTemplate = declTemplate;
+ ClassKind(String typeStr, InterfaceKind... superInterfaces) {
this.typeStr = typeStr;
this.superInterfaces = List.from(superInterfaces);
}
- String getDecl(ModifierKind mod) {
- return declTemplate != null ?
- declTemplate.replaceAll("#M", mod.modStr) :
- "";
- }
-
@Override
public boolean subtypeOf(Type that) {
return this == that || superInterfaces.contains(that) ||
@@ -137,11 +115,6 @@
}
@Override
- public String asString() {
- return typeStr;
- }
-
- @Override
public boolean isClass() {
return true;
}
@@ -150,9 +123,14 @@
public boolean isInterface() {
return false;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return typeStr;
+ }
}
- enum ModifierKind {
+ enum ModifierKind implements ComboParameter {
NONE(""),
FINAL("final");
@@ -161,14 +139,18 @@
ModifierKind(String modStr) {
this.modStr = modStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return modStr;
+ }
}
- enum CastKind {
- CLASS("(#C)", 0),
- INTERFACE("(#I0)", 1),
- INTERSECTION2("(#C & #I0)", 1),
- INTERSECTION3("(#C & #I0 & #I1)", 2);
- //INTERSECTION4("(#C & #I0 & #I1 & #I2)", 3);
+ enum CastKind implements ComboParameter {
+ CLASS("(#{CLAZZ#IDX})", 0),
+ INTERFACE("(#{INTF1#IDX})", 1),
+ INTERSECTION2("(#{CLAZZ#IDX} & #{INTF1#IDX})", 1),
+ INTERSECTION3("(#{CLAZZ#IDX} & #{INTF1#IDX} & #{INTF2#IDX})", 2);
String castTemplate;
int interfaceBounds;
@@ -177,6 +159,11 @@
this.castTemplate = castTemplate;
this.interfaceBounds = interfaceBounds;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return castTemplate.replaceAll("#IDX", optParameter);
+ }
}
static class CastInfo {
@@ -188,19 +175,9 @@
this.types = types;
}
- String getCast() {
- String temp = kind.castTemplate.replaceAll("#C",
- types[0].asString());
- for (int i = 0; i < kind.interfaceBounds ; i++) {
- temp = temp.replace(String.format("#I%d", i),
- types[i + 1].asString());
- }
- return temp;
- }
-
boolean hasDuplicateTypes() {
- for (int i = 0 ; i < types.length ; i++) {
- for (int j = 0 ; j < types.length ; j++) {
+ for (int i = 0 ; i < arity() ; i++) {
+ for (int j = 0 ; j < arity() ; j++) {
if (i != j && types[i] == types[j]) {
return true;
}
@@ -210,8 +187,10 @@
}
boolean compatibleWith(ModifierKind mod, CastInfo that) {
- for (Type t1 : types) {
- for (Type t2 : that.types) {
+ for (int i = 0 ; i < arity() ; i++) {
+ Type t1 = types[i];
+ for (int j = 0 ; j < that.arity() ; j++) {
+ Type t2 = that.types[j];
boolean compat =
t1.subtypeOf(t2) ||
t2.subtypeOf(t1) ||
@@ -223,138 +202,92 @@
}
return true;
}
+
+ private int arity() {
+ return kind.interfaceBounds + 1;
+ }
}
public static void main(String... args) throws Exception {
- for (ModifierKind mod : ModifierKind.values()) {
- for (CastInfo cast1 : allCastInfo()) {
- for (CastInfo cast2 : allCastInfo()) {
- pool.execute(
- new IntersectionTypeCastTest(mod, cast1, cast2));
+ new ComboTestHelper<IntersectionTypeCastTest>()
+ .withFilter(IntersectionTypeCastTest::isRedundantCast)
+ .withFilter(IntersectionTypeCastTest::arityFilter)
+ .withArrayDimension("CAST", (x, ck, idx) -> x.castKinds[idx] = ck, 2, CastKind.values())
+ .withDimension("CLAZZ1", (x, ty) -> x.types1[0] = ty, ClassKind.values())
+ .withDimension("INTF11", (x, ty) -> x.types1[1] = ty, InterfaceKind.values())
+ .withDimension("INTF21", (x, ty) -> x.types1[2] = ty, InterfaceKind.values())
+ .withDimension("CLAZZ2", (x, ty) -> x.types2[0] = ty, ClassKind.values())
+ .withDimension("INTF12", (x, ty) -> x.types2[1] = ty, InterfaceKind.values())
+ .withDimension("INTF22", (x, ty) -> x.types2[2] = ty, InterfaceKind.values())
+ .withDimension("MOD", (x, mod) -> x.mod = mod, ModifierKind.values())
+ .run(IntersectionTypeCastTest::new);
+ }
+
+ boolean isRedundantCast() {
+ for (int i = 0 ; i < 2 ; i++) {
+ Type[] types = i == 0 ? types1 : types2;
+ if (castKinds[i] == CastKind.INTERFACE && types[0] != ClassKind.OBJECT) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ boolean arityFilter() {
+ for (int i = 0 ; i < 2 ; i++) {
+ int lastPos = castKinds[i].interfaceBounds + 1;
+ Type[] types = i == 0 ? types1 : types2;
+ for (int j = 1; j < types.length; j++) {
+ boolean shouldBeSet = j < lastPos;
+ if (!shouldBeSet && (types[j] != InterfaceKind.A)) {
+ return false;
}
}
}
- checkAfterExec();
- }
-
- static List<CastInfo> allCastInfo() {
- ListBuffer<CastInfo> buf = new ListBuffer<>();
- for (CastKind kind : CastKind.values()) {
- for (ClassKind clazz : ClassKind.values()) {
- if (kind == CastKind.INTERFACE && clazz != ClassKind.OBJECT) {
- continue;
- } else if (kind.interfaceBounds == 0) {
- buf.append(new CastInfo(kind, clazz));
- continue;
- } else {
- for (InterfaceKind intf1 : InterfaceKind.values()) {
- if (kind.interfaceBounds == 1) {
- buf.append(new CastInfo(kind, clazz, intf1));
- continue;
- } else {
- for (InterfaceKind intf2 : InterfaceKind.values()) {
- if (kind.interfaceBounds == 2) {
- buf.append(
- new CastInfo(kind, clazz, intf1, intf2));
- continue;
- } else {
- for (InterfaceKind intf3 : InterfaceKind.values()) {
- buf.append(
- new CastInfo(kind, clazz, intf1,
- intf2, intf3));
- continue;
- }
- }
- }
- }
- }
- }
- }
- }
- return buf.toList();
+ return true;
}
ModifierKind mod;
- CastInfo cast1, cast2;
- JavaSource source;
- DiagnosticChecker diagChecker;
-
- IntersectionTypeCastTest(ModifierKind mod, CastInfo cast1, CastInfo cast2) {
- this.mod = mod;
- this.cast1 = cast1;
- this.cast2 = cast2;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
- }
+ CastKind[] castKinds = new CastKind[2];
+ Type[] types1 = new Type[3];
+ Type[] types2 = new Type[3];
@Override
- public void run() {
- final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-
- JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
- null, null, Arrays.asList(source));
- try {
- ct.analyze();
- } catch (Throwable ex) {
- throw new AssertionError("Error thrown when compiling the following code:\n" +
- source.getCharContent(true));
- }
- check();
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withSourceFromTemplate(bodyTemplate)
+ .analyze());
}
- class JavaSource extends SimpleJavaFileObject {
-
- String bodyTemplate = "class Test {\n" +
- " void test() {\n" +
- " Object o = #C1#C2null;\n" +
- " } }";
-
- String source = "";
+ String bodyTemplate = "class Test {\n" +
+ " void test() {\n" +
+ " Object o = #{CAST[0].1}#{CAST[1].2}null;\n" +
+ " } }\n" +
+ "interface A { }\n" +
+ "interface B { }\n" +
+ "interface C extends A { }\n" +
+ "#{MOD} class CA implements A { }\n" +
+ "#{MOD} class CB implements B { }\n" +
+ "#{MOD} class CAB implements A, B { }\n" +
+ "#{MOD} class CC implements C { }\n" +
+ "#{MOD} class CCA implements C, A { }\n" +
+ "#{MOD} class CCB implements C, B { }\n" +
+ "#{MOD} class CCAB implements C, A, B { }";
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- for (ClassKind ck : ClassKind.values()) {
- source += ck.getDecl(mod);
- }
- for (InterfaceKind ik : InterfaceKind.values()) {
- source += ik.declStr;
- }
- source += bodyTemplate.replaceAll("#C1", cast1.getCast()).
- replaceAll("#C2", cast2.getCast());
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
- }
-
- void check() {
- checkCount.incrementAndGet();
-
+ void check(Result<?> res) {
+ CastInfo cast1 = new CastInfo(castKinds[0], types1);
+ CastInfo cast2 = new CastInfo(castKinds[1], types2);
boolean errorExpected = cast1.hasDuplicateTypes() ||
cast2.hasDuplicateTypes();
errorExpected |= !cast2.compatibleWith(mod, cast1);
- if (errorExpected != diagChecker.errorFound) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nFound error: " + diagChecker.errorFound +
+ boolean errorsFound = res.hasErrors();
+ if (errorExpected != errorsFound) {
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
+ "\nFound error: " + errorsFound +
"\nExpected error: " + errorExpected);
}
}
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- a/langtools/test/tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,40 +23,41 @@
/*
* @test
- * @bug 8005166
+ * @bug 8005166 8129962
* @summary Add support for static interface methods
* Smoke test for static interface method hiding
- * @modules jdk.compiler
- * @run main/timeout=600 InterfaceMethodHidingTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main InterfaceMethodHidingTest
*/
-import com.sun.source.util.JavacTask;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
+import java.io.IOException;
+
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
-
-public class InterfaceMethodHidingTest {
-
- static int checkCount = 0;
+public class InterfaceMethodHidingTest extends ComboInstance<InterfaceMethodHidingTest> {
- enum SignatureKind {
- VOID_INTEGER("void m(Integer s)", "return;"),
- STRING_INTEGER("String m(Integer s)", "return null;"),
- VOID_STRING("void m(String s)", "return;"),
- STRING_STRING("String m(String s)", "return null;");
+ enum SignatureKind implements ComboParameter {
+ VOID_INTEGER("void m(Integer s)", false),
+ STRING_INTEGER("String m(Integer s)", true),
+ VOID_STRING("void m(String s)", false),
+ STRING_STRING("String m(String s)", true);
String sigStr;
- String retStr;
+ boolean needsReturn;
- SignatureKind(String sigStr, String retStr) {
+ SignatureKind(String sigStr, boolean needsReturn) {
this.sigStr = sigStr;
- this.retStr = retStr;
+ this.needsReturn = needsReturn;
}
boolean overrideEquivalentWith(SignatureKind s2) {
@@ -71,18 +72,21 @@
throw new AssertionError("bad signature kind");
}
}
+
+ @Override
+ public String expand(String optParameter) {
+ return sigStr;
+ }
}
- enum MethodKind {
- VIRTUAL("", "#M #S;"),
- STATIC("static", "#M #S { #BE; #R }"),
- DEFAULT("default", "#M #S { #BE; #R }");
+ enum MethodKind implements ComboParameter {
+ VIRTUAL("#{SIG[#IDX]};"),
+ STATIC("static #{SIG[#IDX]} { #{BODY[#IDX]}; #{RET.#IDX} }"),
+ DEFAULT("default #{SIG[#IDX]} { #{BODY[#IDX]}; #{RET.#IDX} }");
- String modStr;
String methTemplate;
- MethodKind(String modStr, String methTemplate) {
- this.modStr = modStr;
+ MethodKind(String methTemplate) {
this.methTemplate = methTemplate;
}
@@ -96,15 +100,13 @@
mk1 != STATIC;
}
- String getBody(BodyExpr be, SignatureKind sk) {
- return methTemplate.replaceAll("#BE", be.bodyExprStr)
- .replaceAll("#R", sk.retStr)
- .replaceAll("#M", modStr)
- .replaceAll("#S", sk.sigStr);
+ @Override
+ public String expand(String optParameter) {
+ return methTemplate.replaceAll("#IDX", optParameter);
}
}
- enum BodyExpr {
+ enum BodyExpr implements ComboParameter {
NONE(""),
THIS("Object o = this");
@@ -118,129 +120,78 @@
return this == NONE ||
mk != MethodKind.STATIC;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return bodyExprStr;
+ }
}
public static void main(String... args) throws Exception {
-
- //create default shared JavaCompiler - reused across multiple compilations
- JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
- try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) {
-
- for (MethodKind mk1 : MethodKind.values()) {
- for (SignatureKind sk1 : SignatureKind.values()) {
- for (BodyExpr be1 : BodyExpr.values()) {
- for (MethodKind mk2 : MethodKind.values()) {
- for (SignatureKind sk2 : SignatureKind.values()) {
- for (BodyExpr be2 : BodyExpr.values()) {
- for (MethodKind mk3 : MethodKind.values()) {
- for (SignatureKind sk3 : SignatureKind.values()) {
- for (BodyExpr be3 : BodyExpr.values()) {
- new InterfaceMethodHidingTest(mk1, mk2, mk3, sk1, sk2, sk3, be1, be2, be3).run(comp, fm);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- System.out.println("Total check executed: " + checkCount);
- }
+ new ComboTestHelper<InterfaceMethodHidingTest>()
+ .withArrayDimension("SIG", (x, sig, idx) -> x.signatureKinds[idx] = sig, 3, SignatureKind.values())
+ .withArrayDimension("BODY", (x, body, idx) -> x.bodyExprs[idx] = body, 3, BodyExpr.values())
+ .withArrayDimension("MET", (x, meth, idx) -> x.methodKinds[idx] = meth, 3, MethodKind.values())
+ .run(InterfaceMethodHidingTest::new);
}
- MethodKind mk1, mk2, mk3;
- SignatureKind sk1, sk2, sk3;
- BodyExpr be1, be2, be3;
- JavaSource source;
- DiagnosticChecker diagChecker;
+ MethodKind[] methodKinds = new MethodKind[3];
+ SignatureKind[] signatureKinds = new SignatureKind[3];
+ BodyExpr[] bodyExprs = new BodyExpr[3];
- InterfaceMethodHidingTest(MethodKind mk1, MethodKind mk2, MethodKind mk3,
- SignatureKind sk1, SignatureKind sk2, SignatureKind sk3, BodyExpr be1, BodyExpr be2, BodyExpr be3) {
- this.mk1 = mk1;
- this.mk2 = mk2;
- this.mk3 = mk3;
- this.sk1 = sk1;
- this.sk2 = sk2;
- this.sk3 = sk3;
- this.be1 = be1;
- this.be2 = be2;
- this.be3 = be3;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
- }
-
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "interface Sup {\n" +
+ String template = "interface Sup {\n" +
" default void sup() { }\n" +
"}\n" +
"interface A extends Sup {\n" +
- " #M1\n" +
+ " #{MET[0].0}\n" +
"}\n" +
"interface B extends A, Sup {\n" +
- " #M2\n" +
+ " #{MET[1].1}\n" +
"}\n" +
"interface C extends B, Sup {\n" +
- " #M3\n" +
+ " #{MET[2].2}\n" +
"}\n";
- String source;
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withOption("-XDallowStaticInterfaceMethods")
+ .withSourceFromTemplate(template, this::returnExpr)
+ .analyze());
+ }
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replaceAll("#M1", mk1.getBody(be1, sk1))
- .replaceAll("#M2", mk2.getBody(be2, sk2))
- .replaceAll("#M3", mk3.getBody(be3, sk3));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
+ ComboParameter returnExpr(String name) {
+ switch (name) {
+ case "RET":
+ return optParameter -> {
+ int idx = new Integer(optParameter);
+ return signatureKinds[idx].needsReturn ? "return null;" : "return;";
+ };
+ default:
+ return null;
}
}
- void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
- JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
- Arrays.asList("-XDallowStaticInterfaceMethods"), null, Arrays.asList(source));
- try {
- ct.analyze();
- } catch (Throwable ex) {
- throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true));
- }
- check();
- }
+ void check(Result<?> res) {
+ boolean errorExpected = !bodyExprs[0].allowed(methodKinds[0]) ||
+ !bodyExprs[1].allowed(methodKinds[1]) ||
+ !bodyExprs[2].allowed(methodKinds[2]);
- void check() {
- boolean errorExpected =
- !be1.allowed(mk1) || !be2.allowed(mk2) || !be3.allowed(mk3);
-
- if (mk1.inherithed()) {
- errorExpected |=
- sk2.overrideEquivalentWith(sk1) && !MethodKind.overrides(mk2, sk2, mk1, sk1) ||
- sk3.overrideEquivalentWith(sk1) && !MethodKind.overrides(mk3, sk3, mk1, sk1);
+ if (methodKinds[0].inherithed()) {
+ errorExpected |= signatureKinds[1].overrideEquivalentWith(signatureKinds[0]) &&
+ !MethodKind.overrides(methodKinds[1], signatureKinds[1], methodKinds[0], signatureKinds[0]) ||
+ signatureKinds[2].overrideEquivalentWith(signatureKinds[0]) &&
+ !MethodKind.overrides(methodKinds[2], signatureKinds[2], methodKinds[0], signatureKinds[0]);
}
- if (mk2.inherithed()) {
- errorExpected |=
- sk3.overrideEquivalentWith(sk2) && !MethodKind.overrides(mk3, sk3, mk2, sk2);
+ if (methodKinds[1].inherithed()) {
+ errorExpected |= signatureKinds[2].overrideEquivalentWith(signatureKinds[1]) &&
+ !MethodKind.overrides(methodKinds[2], signatureKinds[2], methodKinds[1], signatureKinds[1]);
}
- checkCount++;
- if (diagChecker.errorFound != errorExpected) {
- throw new AssertionError("Problem when compiling source:\n" + source.getCharContent(true) +
- "\nfound error: " + diagChecker.errorFound);
- }
- }
-
- static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
+ if (res.hasErrors() != errorExpected) {
+ fail("Problem when compiling source:\n" + res.compilationInfo() +
+ "\nfound error: " + res.hasErrors());
}
}
}
--- a/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,33 +23,32 @@
/*
* @test
- * @bug 7192246 8006694
+ * @bug 7192246 8006694 8129962
* @summary Automatic test for checking correctness of default super/this resolution
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm TestDefaultSuperCall
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main TestDefaultSuperCall
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
-import java.net.URI;
-import java.util.Arrays;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-
-import com.sun.source.util.JavacTask;
-public class TestDefaultSuperCall
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
- enum InterfaceKind {
+public class TestDefaultSuperCall extends ComboInstance<TestDefaultSuperCall> {
+
+ enum InterfaceKind implements ComboParameter {
DEFAULT("interface A extends B { default void m() { } }"),
ABSTRACT("interface A extends B { void m(); }"),
NONE("interface A extends B { }");
@@ -63,9 +62,14 @@
boolean methodDefined() {
return this == DEFAULT;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return interfaceStr;
+ }
}
- enum PruneKind {
+ enum PruneKind implements ComboParameter {
NO_PRUNE("interface C { }"),
PRUNE("interface C extends A { }");
@@ -79,15 +83,20 @@
PruneKind(String interfaceStr) {
this.interfaceStr = interfaceStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return interfaceStr;
+ }
}
- enum QualifierKind {
+ enum QualifierKind implements ComboParameter {
DIRECT_1("C"),
DIRECT_2("A"),
INDIRECT("B"),
UNRELATED("E"),
- ENCLOSING_1(null),
- ENCLOSING_2(null);
+ ENCLOSING_1("name0"),
+ ENCLOSING_2("name1");
String qualifierStr;
@@ -95,15 +104,6 @@
this.qualifierStr = qualifierStr;
}
- String getQualifier(Shape sh) {
- switch (this) {
- case ENCLOSING_1: return sh.enclosingAt(0);
- case ENCLOSING_2: return sh.enclosingAt(1);
- default:
- return qualifierStr;
- }
- }
-
boolean isEnclosing() {
return this == ENCLOSING_1 ||
this == ENCLOSING_2;
@@ -119,9 +119,14 @@
return false;
}
}
+
+ @Override
+ public String expand(String optParameter) {
+ return qualifierStr;
+ }
}
- enum ExprKind {
+ enum ExprKind implements ComboParameter {
THIS("this"),
SUPER("super");
@@ -130,19 +135,24 @@
ExprKind(String exprStr) {
this.exprStr = exprStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return exprStr;
+ }
}
- enum ElementKind {
- INTERFACE("interface #N { #B }", true),
- INTERFACE_EXTENDS("interface #N extends A, C { #B }", true),
- CLASS("class #N { #B }", false),
- CLASS_EXTENDS("abstract class #N implements A, C { #B }", false),
- STATIC_CLASS("static class #N { #B }", true),
- STATIC_CLASS_EXTENDS("abstract static class #N implements A, C { #B }", true),
- ANON_CLASS("new Object() { #B };", false),
- METHOD("void test() { #B }", false),
- STATIC_METHOD("static void test() { #B }", true),
- DEFAULT_METHOD("default void test() { #B }", false);
+ enum ElementKind implements ComboParameter {
+ INTERFACE("interface name#CURR { #BODY }", true),
+ INTERFACE_EXTENDS("interface name#CURR extends A, C { #BODY }", true),
+ CLASS("class name#CURR { #BODY }", false),
+ CLASS_EXTENDS("abstract class name#CURR implements A, C { #BODY }", false),
+ STATIC_CLASS("static class name#CURR { #BODY }", true),
+ STATIC_CLASS_EXTENDS("abstract static class name#CURR implements A, C { #BODY }", true),
+ ANON_CLASS("new Object() { #BODY };", false),
+ METHOD("void test() { #BODY }", false),
+ STATIC_METHOD("static void test() { #BODY }", true),
+ DEFAULT_METHOD("default void test() { #BODY }", false);
String templateDecl;
boolean isStatic;
@@ -207,11 +217,21 @@
this == STATIC_CLASS_EXTENDS ||
this == CLASS_EXTENDS;
}
+
+ @Override
+ public String expand(String optParameter) {
+ int nextDepth = new Integer(optParameter) + 1;
+ String replStr = (nextDepth <= 4) ?
+ String.format("#{ELEM[%d].%d}", nextDepth, nextDepth) :
+ "#{QUAL}.#{EXPR}.#{METH}();";
+ return templateDecl
+ .replaceAll("#CURR", optParameter)
+ .replaceAll("#BODY", replStr);
+ }
}
static class Shape {
- String shapeStr;
List<ElementKind> enclosingElements;
List<String> enclosingNames;
List<String> elementsWithMethod;
@@ -234,114 +254,73 @@
} else {
elementsWithMethod.add(prevName);
}
- String element = ek.templateDecl.replaceAll("#N", name);
- shapeStr = shapeStr ==
- null ? element : shapeStr.replaceAll("#B", element);
prevName = name;
}
}
-
- String getShape(QualifierKind qk, ExprKind ek) {
- String methName = ek == ExprKind.THIS ? "test" : "m";
- String call = qk.getQualifier(this) + "." +
- ek.exprStr + "." + methName + "();";
- return shapeStr.replaceAll("#B", call);
- }
-
- String enclosingAt(int index) {
- return index < enclosingNames.size() ?
- enclosingNames.get(index) : "BAD";
- }
}
public static void main(String... args) throws Exception {
- for (InterfaceKind ik : InterfaceKind.values()) {
- for (PruneKind pk : PruneKind.values()) {
- for (ElementKind ek1 : ElementKind.values()) {
- if (!ek1.isAllowedTop()) continue;
- for (ElementKind ek2 : ElementKind.values()) {
- if (!ek2.isAllowedEnclosing(ek1, true)) continue;
- for (ElementKind ek3 : ElementKind.values()) {
- if (!ek3.isAllowedEnclosing(ek2, false)) continue;
- for (ElementKind ek4 : ElementKind.values()) {
- if (!ek4.isAllowedEnclosing(ek3, false)) continue;
- for (ElementKind ek5 : ElementKind.values()) {
- if (!ek5.isAllowedEnclosing(ek4, false) ||
- ek5.isClassDecl()) continue;
- for (QualifierKind qk : QualifierKind.values()) {
- for (ExprKind ek : ExprKind.values()) {
- pool.execute(
- new TestDefaultSuperCall(ik, pk,
- new Shape(ek1, ek2, ek3,
- ek4, ek5), qk, ek));
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
+ new ComboTestHelper<TestDefaultSuperCall>()
+ .withFilter(TestDefaultSuperCall::filterBadTopElement)
+ .withFilter(TestDefaultSuperCall::filterBadIntermediateElement)
+ .withFilter(TestDefaultSuperCall::filterBadTerminalElement)
+ .withDimension("INTF1", (x, ik) -> x.ik = ik, InterfaceKind.values())
+ .withDimension("INTF2", (x, pk) -> x.pk = pk, PruneKind.values())
+ .withArrayDimension("ELEM", (x, elem, idx) -> x.elements[idx] = elem, 5, ElementKind.values())
+ .withDimension("QUAL", (x, qk) -> x.qk = qk, QualifierKind.values())
+ .withDimension("EXPR", (x, ek) -> x.ek = ek, ExprKind.values())
+ .run(TestDefaultSuperCall::new);
}
InterfaceKind ik;
PruneKind pk;
- Shape sh;
+ ElementKind[] elements = new ElementKind[5];
QualifierKind qk;
ExprKind ek;
- JavaSource source;
- DiagnosticChecker diagChecker;
+
+ boolean filterBadTopElement() {
+ return elements[0].isAllowedTop();
+ }
- TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh,
- QualifierKind qk, ExprKind ek) {
- this.ik = ik;
- this.pk = pk;
- this.sh = sh;
- this.qk = qk;
- this.ek = ek;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
+ boolean filterBadIntermediateElement() {
+ for (int i = 1 ; i < 4 ; i++) {
+ if (!elements[i].isAllowedEnclosing(elements[i - 1], i == 1)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ boolean filterBadTerminalElement() {
+ return elements[4].isAllowedEnclosing(elements[3], false) && !elements[4].isClassDecl();
}
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "interface E {}\n" +
- "interface B { }\n" +
- "#I\n" +
- "#P\n" +
- "#C";
-
- String source;
+ String template = "interface E {}\n" +
+ "interface B { }\n" +
+ "#{INTF1}\n" +
+ "#{INTF2}\n" +
+ "#{ELEM[0].0}";
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replaceAll("#I", ik.interfaceStr)
- .replaceAll("#P", pk.interfaceStr)
- .replaceAll("#C", sh.getShape(qk, ek));
- }
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withSourceFromTemplate(template, this::methodName)
+ .analyze());
+ }
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
+ ComboParameter methodName(String parameterName) {
+ switch (parameterName) {
+ case "METH":
+ String methodName = ek == ExprKind.THIS ? "test" : "m";
+ return new ComboParameter.Constant<String>(methodName);
+ default:
+ return null;
}
}
- public void run() {
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
- null, null, Arrays.asList(source));
- try {
- ct.analyze();
- } catch (Throwable ex) {
- processException(ex);
- return;
- }
- check();
- }
+ void check(Result<?> res) {
+ Shape sh = new Shape(elements);
- void check() {
boolean errorExpected = false;
boolean badEnclosing = false;
@@ -364,7 +343,7 @@
boolean found = false;
for (int i = 0; i < sh.enclosingElements.size(); i++) {
if (sh.enclosingElements.get(i) == ElementKind.ANON_CLASS) continue;
- if (sh.enclosingNames.get(i).equals(qk.getQualifier(sh))) {
+ if (sh.enclosingNames.get(i).equals(qk.qualifierStr)) {
found = sh.elementsWithMethod.contains(sh.enclosingNames.get(i));
break;
}
@@ -388,10 +367,9 @@
}
}
- checkCount.incrementAndGet();
- if (diagChecker.errorFound != errorExpected) {
- throw new AssertionError("Problem when compiling source:\n" +
- source.getCharContent(true) +
+ if (res.hasErrors() != errorExpected) {
+ fail("Problem when compiling source:\n" +
+ res.compilationInfo() +
"\nenclosingElems: " + sh.enclosingElements +
"\nenclosingNames: " + sh.enclosingNames +
"\nelementsWithMethod: " + sh.elementsWithMethod +
@@ -399,20 +377,7 @@
"\nbad this: " + badThis +
"\nbad super: " + badSuper +
"\nqual kind: " + qk +
- "\nfound error: " + diagChecker.errorFound);
+ "\nfound error: " + res.hasErrors());
}
}
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- a/langtools/test/tools/javac/failover/CheckAttributedTree.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/failover/CheckAttributedTree.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6970584 8006694 8062373
+ * @bug 6970584 8006694 8062373 8129962
* @summary assorted position errors in compiler syntax trees
* temporarily workaround combo tests are causing time out in several platforms
* @library ../lib
@@ -31,13 +31,10 @@
* jdk.compiler/com.sun.tools.javac.code
* jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm CheckAttributedTree -q -r -et ERRONEOUS .
+ * @build combo.ComboTestHelper
+ * @run main CheckAttributedTree -q -r -et ERRONEOUS .
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
@@ -56,6 +53,11 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -79,18 +81,14 @@
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
-import javax.tools.Diagnostic;
-import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import com.sun.source.tree.CompilationUnitTree;
-import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskEvent.Kind;
import com.sun.source.util.TaskListener;
-import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.EndPosTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
@@ -101,6 +99,10 @@
import static com.sun.tools.javac.tree.JCTree.Tag.*;
+import combo.ComboTestHelper;
+import combo.ComboInstance;
+import combo.ComboTestHelper.IgnoreMode;
+
/**
* Utility and test program to check validity of tree positions for tree nodes.
* The program can be run standalone, or as a jtreg test. In standalone mode,
@@ -113,7 +115,7 @@
* covering any new language features that may be tested in this test suite.
*/
-public class CheckAttributedTree extends JavacTestingAbstractThreadedTest {
+public class CheckAttributedTree {
/**
* Main entry point.
* If test.src is set, program runs in jtreg mode, and will throw an Error
@@ -125,7 +127,6 @@
public static void main(String... args) throws Exception {
String testSrc = System.getProperty("test.src");
File baseDir = (testSrc == null) ? null : new File(testSrc);
- throwAssertionOnError = false;
boolean ok = new CheckAttributedTree().run(baseDir, args);
if (!ok) {
if (testSrc != null) // jtreg mode
@@ -160,7 +161,6 @@
quiet = true;
else if (arg.equals("-v")) {
verbose = true;
- printAll = true;
}
else if (arg.equals("-t") && i + 1 < args.length)
tags.add(args[++i]);
@@ -187,18 +187,37 @@
}
}
- for (File file: files) {
- if (file.exists())
- test(file);
- else
- error("File not found: " + file);
- }
+ ComboTestHelper<FileChecker> cth = new ComboTestHelper<>();
+ cth.withIgnoreMode(IgnoreMode.IGNORE_ALL)
+ .withFilter(FileChecker::checkFile)
+ .withDimension("FILE", (x, file) -> x.file = file, getAllFiles(files))
+ .run(FileChecker::new);
if (fileCount.get() != 1)
errWriter.println(fileCount + " files read");
- checkAfterExec(false);
+
+ if (verbose) {
+ System.out.println(errSWriter.toString());
+ }
+
+ return (gui || !cth.info().hasFailures());
+ }
- return (gui || errCount.get() == 0);
+ File[] getAllFiles(List<File> roots) throws IOException {
+ long now = System.currentTimeMillis();
+ ArrayList<File> buf = new ArrayList<>();
+ for (File file : roots) {
+ Files.walkFileTree(file.toPath(), new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ buf.add(file.toFile());
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ long delta = System.currentTimeMillis() - now;
+ System.err.println("All files = " + buf.size() + " " + delta);
+ return buf.toArray(new File[buf.size()]);
}
/**
@@ -224,116 +243,217 @@
out.println("");
}
- /**
- * Test a file. If the file is a directory, it will be recursively scanned
- * for java files.
- * @param file the file or directory to test
- */
- void test(final File file) {
- if (excludeFiles.contains(file)) {
- if (!quiet)
- error("File " + file + " excluded");
- return;
+ class FileChecker extends ComboInstance<FileChecker> {
+
+ File file;
+
+ boolean checkFile() {
+ if (!file.exists()) {
+ error("File not found: " + file);
+ return false;
+ }
+ if (excludeFiles.contains(file)) {
+ if (!quiet)
+ error("File " + file + " excluded");
+ return false;
+ }
+ if (!file.getName().endsWith(".java")) {
+ if (!quiet)
+ error("File " + file + " ignored");
+ return false;
+ }
+
+ return true;
}
- if (file.isDirectory()) {
- for (File f: file.listFiles()) {
- test(f);
+ public void doWork() {
+ if (!file.exists()) {
+ error("File not found: " + file);
+ }
+ if (excludeFiles.contains(file)) {
+ if (!quiet)
+ error("File " + file + " excluded");
+ return;
+ }
+ if (!file.getName().endsWith(".java")) {
+ if (!quiet)
+ error("File " + file + " ignored");
+ }
+ try {
+ if (verbose)
+ errWriter.println(file);
+ fileCount.incrementAndGet();
+ NPETester p = new NPETester();
+ p.test(read(file));
+ } catch (AttributionException e) {
+ if (!quiet) {
+ error("Error attributing " + file + "\n" + e.getMessage());
+ }
+ } catch (IOException e) {
+ error("Error reading " + file + ": " + e);
}
- return;
+ }
+
+ /**
+ * Read a file.
+ * @param file the file to be read
+ * @return the tree for the content of the file
+ * @throws IOException if any IO errors occur
+ * @throws AttributionException if any errors occur while analyzing the file
+ */
+ List<Pair<JCCompilationUnit, JCTree>> read(File file) throws IOException, AttributionException {
+ try {
+ Iterable<? extends JavaFileObject> files = fileManager().getJavaFileObjects(file);
+ final List<Element> analyzedElems = new ArrayList<>();
+ final List<CompilationUnitTree> trees = new ArrayList<>();
+ Iterable<? extends Element> elems = newCompilationTask()
+ .withWriter(pw)
+ .withOption("-XDshouldStopPolicy=ATTR")
+ .withOption("-XDverboseCompilePolicy")
+ .withSource(files.iterator().next())
+ .withListener(new TaskListener() {
+ public void started(TaskEvent e) {
+ if (e.getKind() == TaskEvent.Kind.ANALYZE)
+ analyzedElems.add(e.getTypeElement());
+ }
+
+ public void finished(TaskEvent e) {
+ if (e.getKind() == Kind.PARSE)
+ trees.add(e.getCompilationUnit());
+ }
+ }).analyze().get();
+ if (!elems.iterator().hasNext())
+ throw new AttributionException("No results from analyze");
+ List<Pair<JCCompilationUnit, JCTree>> res = new ArrayList<>();
+ for (CompilationUnitTree t : trees) {
+ JCCompilationUnit cu = (JCCompilationUnit)t;
+ for (JCTree def : cu.defs) {
+ if (def.hasTag(CLASSDEF) &&
+ analyzedElems.contains(((JCTree.JCClassDecl)def).sym)) {
+ res.add(new Pair<>(cu, def));
+ }
+ }
+ }
+ return res;
+ }
+ catch (Throwable t) {
+ throw new AttributionException("Exception while attributing file: " + file);
+ }
}
- if (file.isFile() && file.getName().endsWith(".java")) {
- pool.execute(new Runnable() {
- @Override
- public void run() {
+ /**
+ * Report an error. When the program is complete, the program will either
+ * exit or throw an Error if any errors have been reported.
+ * @param msg the error message
+ */
+ void error(String msg) {
+ System.err.println();
+ System.err.println(msg);
+ System.err.println();
+ fail(msg);
+ }
+
+ /**
+ * Main class for testing assertions concerning types/symbol
+ * left uninitialized after attribution
+ */
+ private class NPETester extends TreeScanner {
+ void test(List<Pair<JCCompilationUnit, JCTree>> trees) {
+ for (Pair<JCCompilationUnit, JCTree> p : trees) {
+ sourcefile = p.fst.sourcefile;
+ endPosTable = p.fst.endPositions;
+ encl = new Info(p.snd, endPosTable);
+ p.snd.accept(this);
+ }
+ }
+
+ @Override
+ public void scan(JCTree tree) {
+ if (tree == null ||
+ excludeTags.contains(treeUtil.nameFromTag(tree.getTag()))) {
+ return;
+ }
+
+ Info self = new Info(tree, endPosTable);
+ if (mandatoryType(tree)) {
+ check(tree.type != null,
+ "'null' field 'type' found in tree ", self);
+ if (tree.type==null)
+ Thread.dumpStack();
+ }
+
+ Field errField = checkFields(tree);
+ if (errField!=null) {
+ check(false,
+ "'null' field '" + errField.getName() + "' found in tree ", self);
+ }
+
+ Info prevEncl = encl;
+ encl = self;
+ tree.accept(this);
+ encl = prevEncl;
+ }
+
+ private boolean mandatoryType(JCTree that) {
+ return that instanceof JCTree.JCExpression ||
+ that.hasTag(VARDEF) ||
+ that.hasTag(METHODDEF) ||
+ that.hasTag(CLASSDEF);
+ }
+
+ private final List<String> excludedFields = Arrays.asList("varargsElement", "targetType");
+
+ void check(boolean ok, String label, Info self) {
+ if (!ok) {
+ if (gui) {
+ if (viewer == null)
+ viewer = new Viewer();
+ viewer.addEntry(sourcefile, label, encl, self);
+ }
+ error(label + self.toString() + " encl: " + encl.toString() +
+ " in file: " + sourcefile + " " + self.tree);
+ }
+ }
+
+ Field checkFields(JCTree t) {
+ List<Field> fieldsToCheck = treeUtil.getFieldsOfType(t,
+ excludedFields,
+ Symbol.class,
+ Type.class);
+ for (Field f : fieldsToCheck) {
try {
- if (verbose)
- errWriter.println(file);
- fileCount.incrementAndGet();
- NPETester p = new NPETester();
- p.test(read(file));
- } catch (AttributionException e) {
- if (!quiet) {
- error("Error attributing " + file + "\n" + e.getMessage());
+ if (f.get(t) == null) {
+ return f;
}
- } catch (IOException e) {
- error("Error reading " + file + ": " + e);
+ }
+ catch (IllegalAccessException e) {
+ System.err.println("Cannot read field: " + f);
+ //swallow it
}
}
- });
- return;
+ return null;
+ }
+
+ @Override
+ public void visitImport(JCImport tree) { }
+
+ @Override
+ public void visitTopLevel(JCCompilationUnit tree) {
+ scan(tree.defs);
+ }
+
+ JavaFileObject sourcefile;
+ EndPosTable endPosTable;
+ Info encl;
}
-
- if (!quiet)
- error("File " + file + " ignored");
}
// See CR: 6982992 Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
- Reporter r = new Reporter(pw);
- /**
- * Read a file.
- * @param file the file to be read
- * @return the tree for the content of the file
- * @throws IOException if any IO errors occur
- * @throws AttributionException if any errors occur while analyzing the file
- */
- List<Pair<JCCompilationUnit, JCTree>> read(File file) throws IOException, AttributionException {
- r.errors = 0;
- Iterable<? extends JavaFileObject> files = fm.get().getJavaFileObjects(file);
- String[] opts = { "-XDshouldStopPolicy=ATTR", "-XDverboseCompilePolicy" };
- JavacTask task = (JavacTask)comp.getTask(pw, fm.get(), r, Arrays.asList(opts), null, files);
- final List<Element> analyzedElems = new ArrayList<>();
- task.setTaskListener(new TaskListener() {
- public void started(TaskEvent e) {
- if (e.getKind() == TaskEvent.Kind.ANALYZE)
- analyzedElems.add(e.getTypeElement());
- }
- public void finished(TaskEvent e) { }
- });
- int i = 0;
- try {
- Iterable<? extends CompilationUnitTree> trees = task.parse();
-// JavaCompiler c = JavaCompiler.instance(((JavacTaskImpl) task).getContext());
-// System.err.println("verboseCompilePolicy: " + c.verboseCompilePolicy);
-// System.err.println("shouldStopIfError: " + c.shouldStopPolicyIfError);
-// System.err.println("shouldStopIfNoError: " + c.shouldStopPolicyIfNoError);
- Iterable<? extends Element> elems = task.analyze();
- if (!elems.iterator().hasNext())
- throw new AttributionException("No results from analyze");
- List<Pair<JCCompilationUnit, JCTree>> res = new ArrayList<>();
- //System.err.println("Try to add pairs. Elems are " + analyzedElems);
- for (CompilationUnitTree t : trees) {
- JCCompilationUnit cu = (JCCompilationUnit)t;
- for (JCTree def : cu.defs) {
- if (def.hasTag(CLASSDEF) &&
- analyzedElems.contains(((JCTree.JCClassDecl)def).sym)) {
- //System.err.println("Adding pair..." + cu.sourcefile + " " + ((JCTree.JCClassDecl) def).name);
- res.add((i++ % 2) == 0 ? new Pair<>(cu, def) {} : new Pair<>(cu, def));
- }
- }
- }
- return res;
- }
- catch (Throwable t) {
- throw new AttributionException("Exception while attributing file: " + file);
- }
- }
-
- /**
- * Report an error. When the program is complete, the program will either
- * exit or throw an Error if any errors have been reported.
- * @param msg the error message
- */
- void error(String msg) {
- System.err.println();
- System.err.println(msg);
- System.err.println();
- errCount.incrementAndGet();
- }
+ StringWriter errSWriter = new StringWriter();
+ PrintWriter errWriter = new PrintWriter(errSWriter);
/** Flag: don't report irrelevant files. */
boolean quiet;
@@ -356,101 +476,6 @@
TreeUtil treeUtil = new TreeUtil();
/**
- * Main class for testing assertions concerning types/symbol
- * left uninitialized after attribution
- */
- private class NPETester extends TreeScanner {
- void test(List<Pair<JCCompilationUnit, JCTree>> trees) {
- for (Pair<JCCompilationUnit, JCTree> p : trees) {
-// System.err.println("checking " + p.fst.sourcefile);
- sourcefile = p.fst.sourcefile;
- endPosTable = p.fst.endPositions;
- encl = new Info(p.snd, endPosTable);
- p.snd.accept(this);
- }
- }
-
- @Override
- public void scan(JCTree tree) {
- if (tree == null ||
- excludeTags.contains(treeUtil.nameFromTag(tree.getTag()))) {
- return;
- }
-
- Info self = new Info(tree, endPosTable);
- if (mandatoryType(tree)) {
- check(tree.type != null,
- "'null' field 'type' found in tree ", self);
- if (tree.type==null)
- Thread.dumpStack();
- }
-
- Field errField = checkFields(tree);
- if (errField!=null) {
- check(false,
- "'null' field '" + errField.getName() + "' found in tree ", self);
- }
-
- Info prevEncl = encl;
- encl = self;
- tree.accept(this);
- encl = prevEncl;
- }
-
- private boolean mandatoryType(JCTree that) {
- return that instanceof JCTree.JCExpression ||
- that.hasTag(VARDEF) ||
- that.hasTag(METHODDEF) ||
- that.hasTag(CLASSDEF);
- }
-
- private final List<String> excludedFields = Arrays.asList("varargsElement", "targetType");
-
- void check(boolean ok, String label, Info self) {
- if (!ok) {
- if (gui) {
- if (viewer == null)
- viewer = new Viewer();
- viewer.addEntry(sourcefile, label, encl, self);
- }
- error(label + self.toString() + " encl: " + encl.toString() +
- " in file: " + sourcefile + " " + self.tree);
- }
- }
-
- Field checkFields(JCTree t) {
- List<Field> fieldsToCheck = treeUtil.getFieldsOfType(t,
- excludedFields,
- Symbol.class,
- Type.class);
- for (Field f : fieldsToCheck) {
- try {
- if (f.get(t) == null) {
- return f;
- }
- }
- catch (IllegalAccessException e) {
- System.err.println("Cannot read field: " + f);
- //swallow it
- }
- }
- return null;
- }
-
- @Override
- public void visitImport(JCImport tree) { }
-
- @Override
- public void visitTopLevel(JCCompilationUnit tree) {
- scan(tree.defs);
- }
-
- JavaFileObject sourcefile;
- EndPosTable endPosTable;
- Info encl;
- }
-
- /**
* Utility class providing easy access to position and other info for a tree node.
*/
private class Info {
@@ -524,25 +549,6 @@
}
/**
- * DiagnosticListener to report diagnostics and count any errors that occur.
- */
- private static class Reporter implements DiagnosticListener<JavaFileObject> {
- Reporter(PrintWriter out) {
- this.out = out;
- }
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- //out.println(diagnostic);
- switch (diagnostic.getKind()) {
- case ERROR:
- errors++;
- }
- }
- int errors;
- PrintWriter out;
- }
-
- /**
* GUI viewer for issues found by TreePosTester. The viewer provides a drop
* down list for selecting error conditions, a header area providing details
* about an error, and a text area with the ranges of text highlighted as
--- a/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,30 +23,32 @@
/*
* @test
- * @bug 7046778 8006694
+ * @bug 7046778 8006694 8129962
* @summary Project Coin: problem with diamond and member inner classes
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../../../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm DiamondAndInnerClassTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @compile -Xlint:all DiamondAndInnerClassTest.java
+ * @run main DiamondAndInnerClassTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
-import com.sun.source.util.JavacTask;
-import java.net.URI;
+import java.io.IOException;
import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-public class DiamondAndInnerClassTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+import combo.ComboTestHelper;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
- enum TypeArgumentKind {
+public class DiamondAndInnerClassTest extends ComboInstance<DiamondAndInnerClassTest> {
+
+ enum TypeArgumentKind implements ComboParameter {
NONE(""),
STRING("<String>"),
INTEGER("<Integer>"),
@@ -54,7 +56,7 @@
String typeargStr;
- private TypeArgumentKind(String typeargStr) {
+ TypeArgumentKind(String typeargStr) {
this.typeargStr = typeargStr;
}
@@ -75,252 +77,173 @@
default: throw new AssertionError("Unexpected decl kind: " + this);
}
}
+
+ @Override
+ public String expand(String optParameter) {
+ return typeargStr;
+ }
}
- enum ArgumentKind {
+ enum ArgumentKind implements ComboParameter {
OBJECT("(Object)null"),
STRING("(String)null"),
INTEGER("(Integer)null");
String argStr;
- private ArgumentKind(String argStr) {
+ ArgumentKind(String argStr) {
this.argStr = argStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return argStr;
+ }
}
- enum TypeQualifierArity {
- ONE(1, "A1#TA1"),
- TWO(2, "A1#TA1.A2#TA2"),
- THREE(3, "A1#TA1.A2#TA2.A3#TA3");
+ enum TypeQualifierArity implements ComboParameter {
+ ONE(1, "A1#{TA#IDX[0]}"),
+ TWO(2, "A1#{TA#IDX[0]}.A2#{TA#IDX[1]}"),
+ THREE(3, "A1#{TA#IDX[0]}.A2#{TA#IDX[1]}.A3#{TA#IDX[2]}");
int n;
String qualifierStr;
- private TypeQualifierArity(int n, String qualifierStr) {
+ TypeQualifierArity(int n, String qualifierStr) {
this.n = n;
this.qualifierStr = qualifierStr;
}
- String getType(TypeArgumentKind... typeArgumentKinds) {
- String res = qualifierStr;
- for (int i = 1 ; i <= typeArgumentKinds.length ; i++) {
- res = res.replace("#TA" + i, typeArgumentKinds[i-1].typeargStr);
- }
- return res;
- }
-
- boolean matches(InnerClassDeclArity innerClassDeclArity) {
- return n ==innerClassDeclArity.n;
+ @Override
+ public String expand(String optParameter) {
+ return qualifierStr.replaceAll("#IDX", optParameter);
}
}
- enum InnerClassDeclArity {
- ONE(1, "class A1<X> { A1(X x1) { } #B }"),
- TWO(2, "class A1<X1> { class A2<X2> { A2(X1 x1, X2 x2) { } #B } }"),
- THREE(3, "class A1<X1> { class A2<X2> { class A3<X3> { A3(X1 x1, X2 x2, X3 x3) { } #B } } }");
+ enum InnerClassDeclArity implements ComboParameter {
+ ONE(1, "class A1<X> { A1(X x1) { } #{BODY} }"),
+ TWO(2, "class A1<X1> { class A2<X2> { A2(X1 x1, X2 x2) { } #{BODY} } }"),
+ THREE(3, "class A1<X1> { class A2<X2> { class A3<X3> { A3(X1 x1, X2 x2, X3 x3) { } #{BODY} } } }");
int n;
String classDeclStr;
- private InnerClassDeclArity(int n, String classDeclStr) {
+ InnerClassDeclArity(int n, String classDeclStr) {
this.n = n;
this.classDeclStr = classDeclStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return classDeclStr;
+ }
}
- enum ArgumentListArity {
- ONE(1, "(#A1)"),
- TWO(2, "(#A1,#A2)"),
- THREE(3, "(#A1,#A2,#A3)");
+ enum ArgumentListArity implements ComboParameter {
+ ONE(1, "(#{A[0]})"),
+ TWO(2, "(#{A[0]},#{A[1]})"),
+ THREE(3, "(#{A[0]},#{A[1]},#{A[2]})");
int n;
String argListStr;
- private ArgumentListArity(int n, String argListStr) {
+ ArgumentListArity(int n, String argListStr) {
this.n = n;
this.argListStr = argListStr;
}
- String getArgs(ArgumentKind... argumentKinds) {
- String res = argListStr;
- for (int i = 1 ; i <= argumentKinds.length ; i++) {
- res = res.replace("#A" + i, argumentKinds[i-1].argStr);
- }
- return res;
- }
-
- boolean matches(InnerClassDeclArity innerClassDeclArity) {
- return n ==innerClassDeclArity.n;
+ @Override
+ public String expand(String optParameter) {
+ return argListStr.replaceAll("#IDX", optParameter);
}
}
public static void main(String... args) throws Exception {
- for (InnerClassDeclArity innerClassDeclArity : InnerClassDeclArity.values()) {
- for (TypeQualifierArity declType : TypeQualifierArity.values()) {
- if (!declType.matches(innerClassDeclArity)) continue;
- for (TypeQualifierArity newClassType : TypeQualifierArity.values()) {
- if (!newClassType.matches(innerClassDeclArity)) continue;
- for (ArgumentListArity argList : ArgumentListArity.values()) {
- if (!argList.matches(innerClassDeclArity)) continue;
- for (TypeArgumentKind taDecl1 : TypeArgumentKind.values()) {
- boolean isDeclRaw = taDecl1 == TypeArgumentKind.NONE;
- //no diamond on decl site
- if (taDecl1 == TypeArgumentKind.DIAMOND) continue;
- for (TypeArgumentKind taSite1 : TypeArgumentKind.values()) {
- boolean isSiteRaw =
- taSite1 == TypeArgumentKind.NONE;
- //diamond only allowed on the last type qualifier
- if (taSite1 == TypeArgumentKind.DIAMOND &&
- innerClassDeclArity !=
- InnerClassDeclArity.ONE)
- continue;
- for (ArgumentKind arg1 : ArgumentKind.values()) {
- if (innerClassDeclArity == innerClassDeclArity.ONE) {
- pool.execute(
- new DiamondAndInnerClassTest(
- innerClassDeclArity, declType,
- newClassType, argList,
- new TypeArgumentKind[] {taDecl1},
- new TypeArgumentKind[] {taSite1},
- new ArgumentKind[] {arg1}));
- continue;
- }
- for (TypeArgumentKind taDecl2 : TypeArgumentKind.values()) {
- //no rare types
- if (isDeclRaw != (taDecl2 == TypeArgumentKind.NONE))
- continue;
- //no diamond on decl site
- if (taDecl2 == TypeArgumentKind.DIAMOND)
- continue;
- for (TypeArgumentKind taSite2 : TypeArgumentKind.values()) {
- //no rare types
- if (isSiteRaw != (taSite2 == TypeArgumentKind.NONE))
- continue;
- //diamond only allowed on the last type qualifier
- if (taSite2 == TypeArgumentKind.DIAMOND &&
- innerClassDeclArity != InnerClassDeclArity.TWO)
- continue;
- for (ArgumentKind arg2 : ArgumentKind.values()) {
- if (innerClassDeclArity == innerClassDeclArity.TWO) {
- pool.execute(
- new DiamondAndInnerClassTest(
- innerClassDeclArity,
- declType,
- newClassType,
- argList,
- new TypeArgumentKind[] {taDecl1, taDecl2},
- new TypeArgumentKind[] {taSite1, taSite2},
- new ArgumentKind[] {arg1, arg2}));
- continue;
- }
- for (TypeArgumentKind taDecl3 : TypeArgumentKind.values()) {
- //no rare types
- if (isDeclRaw != (taDecl3 == TypeArgumentKind.NONE))
- continue;
- //no diamond on decl site
- if (taDecl3 == TypeArgumentKind.DIAMOND)
- continue;
- for (TypeArgumentKind taSite3 : TypeArgumentKind.values()) {
- //no rare types
- if (isSiteRaw != (taSite3 == TypeArgumentKind.NONE))
- continue;
- //diamond only allowed on the last type qualifier
- if (taSite3 == TypeArgumentKind.DIAMOND &&
- innerClassDeclArity != InnerClassDeclArity.THREE)
- continue;
- for (ArgumentKind arg3 : ArgumentKind.values()) {
- if (innerClassDeclArity ==
- innerClassDeclArity.THREE) {
- pool.execute(
- new DiamondAndInnerClassTest(
- innerClassDeclArity,
- declType,
- newClassType,
- argList,
- new TypeArgumentKind[] {taDecl1, taDecl2, taDecl3},
- new TypeArgumentKind[] {taSite1, taSite2, taSite3},
- new ArgumentKind[] {arg1, arg2, arg3}));
- continue;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
+ new ComboTestHelper<DiamondAndInnerClassTest>()
+ .withFilter(DiamondAndInnerClassTest::rareTypesFilter)
+ .withFilter(DiamondAndInnerClassTest::noDiamondOnDecl)
+ .withFilter(DiamondAndInnerClassTest::noDiamondOnIntermediateTypes)
+ .withFilter(DiamondAndInnerClassTest::arityMismatch)
+ .withFilter(DiamondAndInnerClassTest::redundantFilter)
+ .withDimension("BODY", new ComboParameter.Constant<>("#{D.1} res = new #{S.2}#{AL};"))
+ .withDimension("DECL", (x, arity) -> x.innerClassDeclArity = arity, InnerClassDeclArity.values())
+ .withDimension("D", (x, arity) -> x.declArity = arity, TypeQualifierArity.values())
+ .withDimension("S", (x, arity) -> x.siteArity = arity, TypeQualifierArity.values())
+ .withDimension("AL", (x, alist) -> x.argumentListArity = alist, ArgumentListArity.values())
+ .withArrayDimension("TA1", (x, targs, idx) -> x.declTypeArgumentKinds[idx] = targs, 3, TypeArgumentKind.values())
+ .withArrayDimension("TA2", (x, targs, idx) -> x.siteTypeArgumentKinds[idx] = targs, 3, TypeArgumentKind.values())
+ .withArrayDimension("A", (x, argsk, idx) -> x.argumentKinds[idx] = argsk, 3, ArgumentKind.values())
+ .run(DiamondAndInnerClassTest::new);
+ }
+
+ InnerClassDeclArity innerClassDeclArity;
+ TypeQualifierArity declArity;
+ TypeQualifierArity siteArity;
+ TypeArgumentKind[] declTypeArgumentKinds = new TypeArgumentKind[3];
+ TypeArgumentKind[] siteTypeArgumentKinds = new TypeArgumentKind[3];
+ ArgumentKind[] argumentKinds = new ArgumentKind[3];
+ ArgumentListArity argumentListArity;
+
+ boolean rareTypesFilter() {
+ for (TypeArgumentKind[] types : Arrays.asList(declTypeArgumentKinds, siteTypeArgumentKinds)) {
+ boolean isRaw = types[0] == TypeArgumentKind.NONE;
+ for (int i = 1; i < innerClassDeclArity.n; i++) {
+ if (isRaw != (types[i] == TypeArgumentKind.NONE)) {
+ return false;
}
}
}
+ return true;
+ }
- checkAfterExec();
+ boolean noDiamondOnDecl() {
+ for (int i = 0; i < innerClassDeclArity.n; i++) {
+ if (declTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ boolean noDiamondOnIntermediateTypes() {
+ for (int i = 0; i < (innerClassDeclArity.n - 1); i++) {
+ if (siteTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND) {
+ return false;
+ }
+ }
+ return true;
}
- InnerClassDeclArity innerClassDeclArity;
- TypeQualifierArity declType;
- TypeQualifierArity siteType;
- ArgumentListArity argList;
- TypeArgumentKind[] declTypeArgumentKinds;
- TypeArgumentKind[] siteTypeArgumentKinds;
- ArgumentKind[] argumentKinds;
- JavaSource source;
- DiagnosticChecker diagChecker;
-
- DiamondAndInnerClassTest(InnerClassDeclArity innerClassDeclArity,
- TypeQualifierArity declType, TypeQualifierArity siteType,
- ArgumentListArity argList, TypeArgumentKind[] declTypeArgumentKinds,
- TypeArgumentKind[] siteTypeArgumentKinds, ArgumentKind[] argumentKinds) {
- this.innerClassDeclArity = innerClassDeclArity;
- this.declType = declType;
- this.siteType = siteType;
- this.argList = argList;
- this.declTypeArgumentKinds = declTypeArgumentKinds;
- this.siteTypeArgumentKinds = siteTypeArgumentKinds;
- this.argumentKinds = argumentKinds;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
+ boolean redundantFilter() {
+ for (TypeArgumentKind[] types : Arrays.asList(declTypeArgumentKinds, siteTypeArgumentKinds)) {
+ for (int i = innerClassDeclArity.n; i < types.length; i++) {
+ if (types[i].ordinal() != 0) {
+ return false;
+ }
+ }
+ }
+ for (int i = innerClassDeclArity.n; i < argumentKinds.length; i++) {
+ if (argumentKinds[i].ordinal() != 0) {
+ return false;
+ }
+ }
+ return true;
}
- class JavaSource extends SimpleJavaFileObject {
-
- String bodyTemplate = "#D res = new #S#AL;";
-
- String source;
-
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = innerClassDeclArity.classDeclStr.replace("#B", bodyTemplate)
- .replace("#D", declType.getType(declTypeArgumentKinds))
- .replace("#S", siteType.getType(siteTypeArgumentKinds))
- .replace("#AL", argList.getArgs(argumentKinds));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
+ boolean arityMismatch() {
+ return argumentListArity.n == innerClassDeclArity.n &&
+ siteArity.n == innerClassDeclArity.n &&
+ declArity.n == innerClassDeclArity.n;
}
@Override
- public void run() {
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
- null, null, Arrays.asList(source));
- try {
- ct.analyze();
- } catch (Throwable ex) {
- throw new AssertionError("Error thrown when compiling the following code:\n" +
- source.getCharContent(true));
- }
- check();
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withSourceFromTemplate("#{DECL}")
+ .analyze());
}
- void check() {
- checkCount.incrementAndGet();
-
+ void check(Result<?> res) {
boolean errorExpected = false;
TypeArgumentKind[] expectedArgKinds =
@@ -345,24 +268,11 @@
}
}
- if (errorExpected != diagChecker.errorFound) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nFound error: " + diagChecker.errorFound +
+ if (errorExpected != res.hasErrors()) {
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
+ "\nFound error: " + res.hasErrors() +
"\nExpected error: " + errorExpected);
}
}
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- a/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,29 +23,29 @@
/*
* @test
- * @bug 7062745 8006694
+ * @bug 7062745 8006694 8129962
* @summary Regression: difference in overload resolution when two methods
* are maximally specific
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../../../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm GenericOverrideTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main GenericOverrideTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import com.sun.source.util.JavacTask;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
-public class GenericOverrideTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+public class GenericOverrideTest extends ComboInstance<GenericOverrideTest> {
enum SourceLevel {
SOURCE_7("-source", "7"),
@@ -58,24 +58,29 @@
}
}
- enum SignatureKind {
+ enum SignatureKind implements ComboParameter {
NON_GENERIC(""),
GENERIC("<X>");
String paramStr;
- private SignatureKind(String paramStr) {
+ SignatureKind(String paramStr) {
this.paramStr = paramStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return paramStr;
+ }
}
- enum ReturnTypeKind {
+ enum ReturnTypeKind implements ComboParameter {
LIST("List"),
ARRAYLIST("ArrayList");
String retStr;
- private ReturnTypeKind(String retStr) {
+ ReturnTypeKind(String retStr) {
this.retStr = retStr;
}
@@ -88,9 +93,14 @@
default: throw new AssertionError("Unexpected ret kind: " + this);
}
}
+
+ @Override
+ public String expand(String optParameter) {
+ return retStr;
+ }
}
- enum TypeArgumentKind {
+ enum TypeArgumentKind implements ComboParameter {
NONE(""),
UNBOUND("<?>"),
INTEGER("<Number>"),
@@ -99,7 +109,7 @@
String typeargStr;
- private TypeArgumentKind(String typeargStr) {
+ TypeArgumentKind(String typeargStr) {
this.typeargStr = typeargStr;
}
@@ -141,136 +151,79 @@
default: throw new AssertionError("Unexpected typearg kind: " + this);
}
}
+
+ @Override
+ public String expand(String optParameter) {
+ return typeargStr;
+ }
}
public static void main(String... args) throws Exception {
- for (SignatureKind sig1 : SignatureKind.values()) {
- for (ReturnTypeKind rt1 : ReturnTypeKind.values()) {
- for (TypeArgumentKind ta1 : TypeArgumentKind.values()) {
- if (!ta1.compatibleWith(sig1)) continue;
- for (SignatureKind sig2 : SignatureKind.values()) {
- for (ReturnTypeKind rt2 : ReturnTypeKind.values()) {
- for (TypeArgumentKind ta2 : TypeArgumentKind.values()) {
- if (!ta2.compatibleWith(sig2)) continue;
- for (ReturnTypeKind rt3 : ReturnTypeKind.values()) {
- for (TypeArgumentKind ta3 : TypeArgumentKind.values()) {
- if (!ta3.compatibleWith(SignatureKind.NON_GENERIC))
- continue;
- for (SourceLevel level : SourceLevel.values()) {
- pool.execute(
- new GenericOverrideTest(sig1,
- rt1, ta1, sig2, rt2,
- ta2, rt3, ta3, level));
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
+ new ComboTestHelper<GenericOverrideTest>()
+ .withFilter(GenericOverrideTest::argMismatchFilter)
+ .withDimension("SOURCE", (x, level) -> x.level = level, SourceLevel.values())
+ .withArrayDimension("SIG", (x, sig, idx) -> x.sigs[idx] = sig, 2, SignatureKind.values())
+ .withArrayDimension("TARG", (x, targ, idx) -> x.targs[idx] = targ, 3, TypeArgumentKind.values())
+ .withArrayDimension("RET", (x, ret, idx) -> x.rets[idx] = ret, 3, ReturnTypeKind.values())
+ .run(GenericOverrideTest::new);
}
- SignatureKind sig1, sig2;
- ReturnTypeKind rt1, rt2, rt3;
- TypeArgumentKind ta1, ta2, ta3;
+ SignatureKind[] sigs = new SignatureKind[2];
+ ReturnTypeKind[] rets = new ReturnTypeKind[3];
+ TypeArgumentKind[] targs = new TypeArgumentKind[3];
SourceLevel level;
- JavaSource source;
- DiagnosticChecker diagChecker;
- GenericOverrideTest(SignatureKind sig1, ReturnTypeKind rt1, TypeArgumentKind ta1,
- SignatureKind sig2, ReturnTypeKind rt2, TypeArgumentKind ta2,
- ReturnTypeKind rt3, TypeArgumentKind ta3, SourceLevel level) {
- this.sig1 = sig1;
- this.sig2 = sig2;
- this.rt1 = rt1;
- this.rt2 = rt2;
- this.rt3 = rt3;
- this.ta1 = ta1;
- this.ta2 = ta2;
- this.ta3 = ta3;
- this.level = level;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
+ boolean argMismatchFilter() {
+ return targs[0].compatibleWith(sigs[0]) &&
+ targs[1].compatibleWith(sigs[1]) &&
+ targs[2].compatibleWith(SignatureKind.NON_GENERIC);
}
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "import java.util.*;\n" +
- "interface A { #S1 #R1#TA1 m(); }\n" +
- "interface B { #S2 #R2#TA2 m(); }\n" +
- "interface AB extends A, B {}\n" +
- "class Test {\n" +
- " void test(AB ab) { #R3#TA3 n = ab.m(); }\n" +
- "}";
-
- String source;
+ String template = "import java.util.*;\n" +
+ "interface A { #{SIG[0]} #{RET[0]}#{TARG[0]} m(); }\n" +
+ "interface B { #{SIG[1]} #{RET[1]}#{TARG[1]} m(); }\n" +
+ "interface AB extends A, B {}\n" +
+ "class Test {\n" +
+ " void test(AB ab) { #{RET[2]}#{TARG[2]} n = ab.m(); }\n" +
+ "}";
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replace("#S1", sig1.paramStr).
- replace("#S2", sig2.paramStr).
- replace("#R1", rt1.retStr).
- replace("#R2", rt2.retStr).
- replace("#R3", rt3.retStr).
- replace("#TA1", ta1.typeargStr).
- replace("#TA2", ta2.typeargStr).
- replace("#TA3", ta3.typeargStr);
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withOption("-XDuseUnsharedTable") //this test relies on predictable name indexes!
+ .withOptions(level.opts)
+ .withSourceFromTemplate(template)
+ .analyze());
}
- @Override
- public void run() {
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
- level.opts != null ? Arrays.asList(level.opts) : null,
- null, Arrays.asList(source));
- try {
- ct.analyze();
- } catch (Throwable ex) {
- throw new AssertionError("Error thrown when compiling the following code:\n" +
- source.getCharContent(true));
- }
- check();
- }
-
- void check() {
- checkCount.incrementAndGet();
-
+ void check(Result<?> res) {
boolean errorExpected = false;
int mostSpecific = 0;
//first check that either |R1| <: |R2| or |R2| <: |R1|
- if (rt1 != rt2) {
- if (!rt1.moreSpecificThan(rt2) &&
- !rt2.moreSpecificThan(rt1)) {
+ if (rets[0] != rets[1]) {
+ if (!rets[0].moreSpecificThan(rets[1]) &&
+ !rets[1].moreSpecificThan(rets[0])) {
errorExpected = true;
} else {
- mostSpecific = rt1.moreSpecificThan(rt2) ? 1 : 2;
+ mostSpecific = rets[0].moreSpecificThan(rets[1]) ? 1 : 2;
}
}
//check that either TA1 <= TA2 or TA2 <= TA1 (unless most specific return found above is raw)
if (!errorExpected) {
- if (ta1 != ta2) {
- boolean useStrictCheck = ta1.moreSpecificThan(ta2, true) ||
- ta2.moreSpecificThan(ta1, true);
- if (!ta1.moreSpecificThan(ta2, useStrictCheck) &&
- !ta2.moreSpecificThan(ta1, useStrictCheck)) {
+ if (targs[0] != targs[1]) {
+ boolean useStrictCheck = targs[0].moreSpecificThan(targs[1], true) ||
+ targs[1].moreSpecificThan(targs[0], true);
+ if (!targs[0].moreSpecificThan(targs[1], useStrictCheck) &&
+ !targs[1].moreSpecificThan(targs[0], useStrictCheck)) {
errorExpected = true;
} else {
- int mostSpecific2 = ta1.moreSpecificThan(ta2, useStrictCheck) ? 1 : 2;
+ int mostSpecific2 = targs[0].moreSpecificThan(targs[1], useStrictCheck) ? 1 : 2;
if (mostSpecific != 0 && mostSpecific2 != mostSpecific) {
errorExpected = mostSpecific == 1 ?
- ta1 != TypeArgumentKind.NONE :
- ta2 != TypeArgumentKind.NONE;
+ targs[0] != TypeArgumentKind.NONE :
+ targs[1] != TypeArgumentKind.NONE;
} else {
mostSpecific = mostSpecific2;
}
@@ -284,34 +237,21 @@
//finally, check that most specific return type is compatible with expected type
if (!errorExpected) {
- ReturnTypeKind msrt = mostSpecific == 1 ? rt1 : rt2;
- TypeArgumentKind msta = mostSpecific == 1 ? ta1 : ta2;
- SignatureKind mssig = mostSpecific == 1 ? sig1 : sig2;
+ ReturnTypeKind msrt = mostSpecific == 1 ? rets[0] : rets[1];
+ TypeArgumentKind msta = mostSpecific == 1 ? targs[0] : targs[1];
+ SignatureKind mssig = mostSpecific == 1 ? sigs[0] : sigs[1];
- if (!msrt.moreSpecificThan(rt3) ||
- !msta.assignableTo(ta3, mssig, level)) {
+ if (!msrt.moreSpecificThan(rets[2]) ||
+ !msta.assignableTo(targs[2], mssig, level)) {
errorExpected = true;
}
}
- if (errorExpected != diagChecker.errorFound) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nFound error: " + diagChecker.errorFound +
+ if (errorExpected != res.hasErrors()) {
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
+ "\nFound error: " + res.hasErrors() +
"\nExpected error: " + errorExpected);
}
}
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- a/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,35 +23,32 @@
/**
* @test
- * @bug 8003280 8004102 8006694
+ * @bug 8003280 8004102 8006694 8129962
* @summary Add lambda tests
* perform several automated checks in lambda conversion, esp. around accessibility
* temporarily workaround combo tests are causing time out in several platforms
- * @author Maurizio Cimadamore
- * @library ../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
- * @run main/timeout=600/othervm FunctionalInterfaceConversionTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main FunctionalInterfaceConversionTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.ToolProvider;
-import com.sun.source.util.JavacTask;
-public class FunctionalInterfaceConversionTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
- enum PackageKind {
+
+public class FunctionalInterfaceConversionTest extends ComboInstance<FunctionalInterfaceConversionTest> {
+
+ enum PackageKind implements ComboParameter {
NO_PKG(""),
PKG_A("a");
@@ -61,7 +58,8 @@
this.pkg = pkg;
}
- String getPkgDecl() {
+ @Override
+ public String expand(String optParameter) {
return this == NO_PKG ?
"" :
"package " + pkg + ";";
@@ -74,12 +72,12 @@
}
}
- enum SamKind {
+ enum SamKind implements ComboParameter {
CLASS("public class Sam { }"),
ABSTACT_CLASS("public abstract class Sam { }"),
ANNOTATION("public @interface Sam { }"),
ENUM("public enum Sam { }"),
- INTERFACE("public interface Sam { \n #METH; \n }");
+ INTERFACE("public interface Sam { \n #{METH1}; \n }");
String sam_str;
@@ -87,12 +85,13 @@
this.sam_str = sam_str;
}
- String getSam(String methStr) {
- return sam_str.replaceAll("#METH", methStr);
+ @Override
+ public String expand(String optParameter) {
+ return sam_str;
}
}
- enum ModifierKind {
+ enum ModifierKind implements ComboParameter {
PUBLIC("public"),
PACKAGE("");
@@ -102,77 +101,73 @@
this.modifier_str = modifier_str;
}
- boolean stricterThan(ModifierKind that) {
- return this.ordinal() > that.ordinal();
+ @Override
+ public String expand(String optParameter) {
+ return modifier_str;
}
}
- enum TypeKind {
+ enum TypeKind implements ComboParameter {
EXCEPTION("Exception"),
PKG_CLASS("PackageClass");
String typeStr;
- private TypeKind(String typeStr) {
+ TypeKind(String typeStr) {
this.typeStr = typeStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return typeStr;
+ }
}
- enum ExprKind {
+ enum ExprKind implements ComboParameter {
LAMBDA("x -> null"),
MREF("this::m");
String exprStr;
- private ExprKind(String exprStr) {
+ ExprKind(String exprStr) {
this.exprStr = exprStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return exprStr;
+ }
}
- enum MethodKind {
+ enum MethodKind implements ComboParameter {
NONE(""),
- NON_GENERIC("public abstract #R m(#ARG s) throws #T;"),
- GENERIC("public abstract <X> #R m(#ARG s) throws #T;");
+ NON_GENERIC("public abstract #{RET} m(#{ARG} s) throws #{THROWN};"),
+ GENERIC("public abstract <X> #{RET} m(#{ARG} s) throws #{THROWN};");
String methodTemplate;
- private MethodKind(String methodTemplate) {
+ MethodKind(String methodTemplate) {
this.methodTemplate = methodTemplate;
}
- String getMethod(TypeKind retType, TypeKind argType, TypeKind thrownType) {
- return methodTemplate.replaceAll("#R", retType.typeStr).
- replaceAll("#ARG", argType.typeStr).
- replaceAll("#T", thrownType.typeStr);
+ @Override
+ public String expand(String optParameter) {
+ return methodTemplate;
}
}
public static void main(String[] args) throws Exception {
- for (PackageKind samPkg : PackageKind.values()) {
- for (ModifierKind modKind : ModifierKind.values()) {
- for (SamKind samKind : SamKind.values()) {
- for (MethodKind samMeth : MethodKind.values()) {
- for (MethodKind clientMeth : MethodKind.values()) {
- for (TypeKind retType : TypeKind.values()) {
- for (TypeKind argType : TypeKind.values()) {
- for (TypeKind thrownType : TypeKind.values()) {
- for (ExprKind exprKind : ExprKind.values()) {
- pool.execute(
- new FunctionalInterfaceConversionTest(
- samPkg, modKind, samKind,
- samMeth, clientMeth, retType,
- argType, thrownType, exprKind));
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec(false);
+ new ComboTestHelper<FunctionalInterfaceConversionTest>()
+ .withDimension("PKG", (x, pkg) -> x.samPkg = pkg, PackageKind.values())
+ .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values())
+ .withDimension("CLAZZ", (x, sam) -> x.samKind = sam, SamKind.values())
+ .withDimension("METH1", (x, meth) -> x.samMeth = meth, MethodKind.values())
+ .withDimension("METH2", (x, meth) -> x.clientMeth = meth, MethodKind.values())
+ .withDimension("RET", (x, ret) -> x.retType = ret, TypeKind.values())
+ .withDimension("ARG", (x, arg) -> x.argType = arg, TypeKind.values())
+ .withDimension("THROWN", (x, thrown) -> x.thrownType = thrown, TypeKind.values())
+ .withDimension("EXPR", (x, expr) -> x.exprKind = expr, ExprKind.values())
+ .run(FunctionalInterfaceConversionTest::new);
}
PackageKind samPkg;
@@ -184,70 +179,32 @@
TypeKind argType;
TypeKind thrownType;
ExprKind exprKind;
- DiagnosticChecker dc;
- SourceFile samSourceFile = new SourceFile("Sam.java", "#P \n #C") {
- @Override
- public String toString() {
- return template.replaceAll("#P", samPkg.getPkgDecl()).
- replaceAll("#C", samKind.getSam(
- samMeth.getMethod(retType, argType, thrownType)));
- }
- };
-
- SourceFile pkgClassSourceFile =
- new SourceFile("PackageClass.java",
- "#P\n #M class PackageClass extends Exception { }") {
- @Override
- public String toString() {
- return template.replaceAll("#P", samPkg.getPkgDecl()).
- replaceAll("#M", modKind.modifier_str);
- }
- };
+ String samSource = "#{PKG} \n #{CLAZZ}";
+ String pkgClassSource = "#{PKG}\n #{MOD} class PackageClass extends Exception { }";
+ String clientSource = "#{IMP}\n abstract class Client { \n" +
+ " Sam s = #{EXPR};\n" +
+ " #{METH2} \n }";
- SourceFile clientSourceFile =
- new SourceFile("Client.java",
- "#I\n abstract class Client { \n" +
- " Sam s = #E;\n" +
- " #M \n }") {
- @Override
- public String toString() {
- return template.replaceAll("#I", samPkg.getImportStat())
- .replaceAll("#E", exprKind.exprStr)
- .replaceAll("#M", clientMeth.getMethod(retType, argType, thrownType));
- }
- };
-
- FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind,
- SamKind samKind, MethodKind samMeth, MethodKind clientMeth,
- TypeKind retType, TypeKind argType, TypeKind thrownType,
- ExprKind exprKind) {
- this.samPkg = samPkg;
- this.modKind = modKind;
- this.samKind = samKind;
- this.samMeth = samMeth;
- this.clientMeth = clientMeth;
- this.retType = retType;
- this.argType = argType;
- this.thrownType = thrownType;
- this.exprKind = exprKind;
- this.dc = new DiagnosticChecker();
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withSourceFromTemplate("Sam", samSource)
+ .withSourceFromTemplate("PackageClass", pkgClassSource)
+ .withSourceFromTemplate("Client", clientSource, this::importStmt)
+ .analyze());
}
- @Override
- public void run() {
- final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+ ComboParameter importStmt(String name) {
+ switch (name) {
+ case "IMP": return new ComboParameter.Constant<>(samPkg.getImportStat());
+ default: return null;
+ }
+ }
- JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc, null, null,
- Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile));
- try {
- ct.analyze();
- } catch (IOException ex) {
- throw new AssertionError("Test failing with cause", ex.getCause());
- }
- if (dc.errorFound == checkSamConversion()) {
- throw new AssertionError(samSourceFile + "\n\n" +
- pkgClassSourceFile + "\n\n" + clientSourceFile);
+ void check(Result<?> res) {
+ if (res.hasErrors() == checkSamConversion()) {
+ fail("Unexpected compilation result; " + res.compilationInfo());
}
}
@@ -276,35 +233,4 @@
return true;
}
}
-
- abstract class SourceFile extends SimpleJavaFileObject {
-
- protected String template;
-
- public SourceFile(String filename, String template) {
- super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
- this.template = template;
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return toString();
- }
-
- @Override
- public abstract String toString();
- }
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound = false;
-
- @Override
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
}
--- a/langtools/test/tools/javac/lambda/LambdaParserTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/lambda/LambdaParserTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,39 +23,40 @@
/*
* @test
- * @bug 7115050 8003280 8005852 8006694
+ * @bug 7115050 8003280 8005852 8006694 8129962
* @summary Add lambda tests
* Add parser support for lambda expressions
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm LambdaParserTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+
+ * @run main LambdaParserTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import com.sun.source.util.JavacTask;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
-public class LambdaParserTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
- enum LambdaKind {
+ enum LambdaKind implements ComboParameter {
NILARY_EXPR("()->x"),
NILARY_STMT("()->{ return x; }"),
- ONEARY_SHORT_EXPR("#PN->x"),
- ONEARY_SHORT_STMT("#PN->{ return x; }"),
- ONEARY_EXPR("(#M1 #T1 #PN)->x"),
- ONEARY_STMT("(#M1 #T1 #PN)->{ return x; }"),
- TWOARY_EXPR("(#M1 #T1 #PN, #M2 #T2 y)->x"),
- TWOARY_STMT("(#M1 #T1 #PN, #M2 #T2 y)->{ return x; }");
+ ONEARY_SHORT_EXPR("#{NAME}->x"),
+ ONEARY_SHORT_STMT("#{NAME}->{ return x; }"),
+ ONEARY_EXPR("(#{MOD[0]} #{TYPE[0]} #{NAME})->x"),
+ ONEARY_STMT("(#{MOD[0]} #{TYPE[0]} #{NAME})->{ return x; }"),
+ TWOARY_EXPR("(#{MOD[0]} #{TYPE[0]} #{NAME}, #{MOD[1]} #{TYPE[1]} y)->x"),
+ TWOARY_STMT("(#{MOD[0]} #{TYPE[0]} #{NAME}, #{MOD[1]} #{TYPE[1]} y)->{ return x; }");
String lambdaTemplate;
@@ -63,13 +64,9 @@
this.lambdaTemplate = lambdaTemplate;
}
- String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2,
- ModifierKind mk1, ModifierKind mk2, LambdaParameterName pn) {
- return lambdaTemplate.replaceAll("#M1", mk1.modifier)
- .replaceAll("#M2", mk2.modifier)
- .replaceAll("#T1", pk1.parameterType)
- .replaceAll("#T2", pk2.parameterType)
- .replaceAll("#PN", pn.nameStr);
+ @Override
+ public String expand(String optParameter) {
+ return lambdaTemplate;
}
int arity() {
@@ -92,7 +89,7 @@
}
}
- enum LambdaParameterName {
+ enum LambdaParameterName implements ComboParameter {
IDENT("x"),
UNDERSCORE("_");
@@ -101,9 +98,14 @@
LambdaParameterName(String nameStr) {
this.nameStr = nameStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return nameStr;
+ }
}
- enum LambdaParameterKind {
+ enum LambdaParameterKind implements ComboParameter {
IMPLICIT(""),
EXPLIICT_SIMPLE("A"),
EXPLIICT_SIMPLE_ARR1("A[]"),
@@ -129,9 +131,14 @@
return this == EXPLICIT_VARARGS ||
this == EXPLICIT_GENERIC2_VARARGS;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return parameterType;
+ }
}
- enum ModifierKind {
+ enum ModifierKind implements ComboParameter {
NONE(""),
FINAL("final"),
PUBLIC("public");
@@ -150,15 +157,20 @@
default: throw new AssertionError("Invalid modifier kind " + this);
}
}
+
+ @Override
+ public String expand(String optParameter) {
+ return modifier;
+ }
}
- enum ExprKind {
- NONE("#L#S"),
- SINGLE_PAREN1("(#L#S)"),
- SINGLE_PAREN2("(#L)#S"),
- DOUBLE_PAREN1("((#L#S))"),
- DOUBLE_PAREN2("((#L)#S)"),
- DOUBLE_PAREN3("((#L))#S");
+ enum ExprKind implements ComboParameter {
+ NONE("#{LAMBDA}#{SUBEXPR}"),
+ SINGLE_PAREN1("(#{LAMBDA}#{SUBEXPR})"),
+ SINGLE_PAREN2("(#{LAMBDA})#{SUBEXPR}"),
+ DOUBLE_PAREN1("((#{LAMBDA}#{SUBEXPR}))"),
+ DOUBLE_PAREN2("((#{LAMBDA})#{SUBEXPR})"),
+ DOUBLE_PAREN3("((#{LAMBDA}))#{SUBEXPR}");
String expressionTemplate;
@@ -166,14 +178,13 @@
this.expressionTemplate = expressionTemplate;
}
- String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2,
- ModifierKind mk1, ModifierKind mk2, LambdaKind lk, LambdaParameterName pn, SubExprKind sk) {
- return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2, pn))
- .replaceAll("#S", sk.subExpression);
+ @Override
+ public String expand(String optParameter) {
+ return expressionTemplate;
}
}
- enum SubExprKind {
+ enum SubExprKind implements ComboParameter {
NONE(""),
SELECT_FIELD(".f"),
SELECT_METHOD(".f()"),
@@ -186,133 +197,78 @@
SubExprKind(String subExpression) {
this.subExpression = subExpression;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return subExpression;
+ }
}
public static void main(String... args) throws Exception {
- for (LambdaKind lk : LambdaKind.values()) {
- for (LambdaParameterName pn : LambdaParameterName.values()) {
- for (LambdaParameterKind pk1 : LambdaParameterKind.values()) {
- if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT)
- continue;
- for (LambdaParameterKind pk2 : LambdaParameterKind.values()) {
- if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT)
- continue;
- for (ModifierKind mk1 : ModifierKind.values()) {
- if (mk1 != ModifierKind.NONE && lk.isShort())
- continue;
- if (lk.arity() < 1 && mk1 != ModifierKind.NONE)
- continue;
- for (ModifierKind mk2 : ModifierKind.values()) {
- if (lk.arity() < 2 && mk2 != ModifierKind.NONE)
- continue;
- for (SubExprKind sk : SubExprKind.values()) {
- for (ExprKind ek : ExprKind.values()) {
- pool.execute(
- new LambdaParserTest(pk1, pk2, mk1,
- mk2, lk, sk, ek, pn));
- }
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
+ new ComboTestHelper<LambdaParserTest>()
+ .withFilter(LambdaParserTest::redundantTestFilter)
+ .withFilter(LambdaParserTest::badImplicitFilter)
+ .withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values())
+ .withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.values())
+ .withArrayDimension("TYPE", (x, type, idx) -> x.pks[idx] = type, 2, LambdaParameterKind.values())
+ .withArrayDimension("MOD", (x, mod, idx) -> x.mks[idx] = mod, 2, ModifierKind.values())
+ .withDimension("EXPR", ExprKind.values())
+ .withDimension("SUBEXPR", SubExprKind.values())
+ .run(LambdaParserTest::new);
}
- LambdaParameterKind pk1;
- LambdaParameterKind pk2;
- ModifierKind mk1;
- ModifierKind mk2;
+ LambdaParameterKind[] pks = new LambdaParameterKind[2];
+ ModifierKind[] mks = new ModifierKind[2];
LambdaKind lk;
LambdaParameterName pn;
- SubExprKind sk;
- ExprKind ek;
- JavaSource source;
- DiagnosticChecker diagChecker;
+
+ boolean badImplicitFilter() {
+ return !(mks[0] != ModifierKind.NONE && lk.isShort());
+ }
- LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2,
- ModifierKind mk1, ModifierKind mk2, LambdaKind lk,
- SubExprKind sk, ExprKind ek, LambdaParameterName pn) {
- this.pk1 = pk1;
- this.pk2 = pk2;
- this.mk1 = mk1;
- this.mk2 = mk2;
- this.lk = lk;
- this.pn = pn;
- this.sk = sk;
- this.ek = ek;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
+ boolean redundantTestFilter() {
+ for (int i = lk.arity(); i < mks.length ; i++) {
+ if (mks[i].ordinal() != 0) {
+ return false;
+ }
+ }
+ for (int i = lk.arity(); i < pks.length ; i++) {
+ if (pks[i].ordinal() != 0) {
+ return false;
+ }
+ }
+ return true;
}
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "class Test {\n" +
- " SAM s = #E;\n" +
- "}";
-
- String source;
+ String template = "class Test {\n" +
+ " SAM s = #{EXPR};\n" +
+ "}";
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replaceAll("#E",
- ek.expressionString(pk1, pk2, mk1, mk2, lk, pn, sk));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withSourceFromTemplate(template)
+ .parse());
}
- public void run() {
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
- null, null, Arrays.asList(source));
- try {
- ct.parse();
- } catch (Throwable ex) {
- processException(ex);
- return;
- }
- check();
- }
-
- void check() {
- checkCount.incrementAndGet();
-
- boolean errorExpected = (lk.arity() > 0 && !mk1.compatibleWith(pk1)) ||
- (lk.arity() > 1 && !mk2.compatibleWith(pk2));
+ void check(Result<?> res) {
+ boolean errorExpected = (lk.arity() > 0 && !mks[0].compatibleWith(pks[0])) ||
+ (lk.arity() > 1 && !mks[1].compatibleWith(pks[1]));
if (lk.arity() == 2 &&
- (pk1.explicit() != pk2.explicit() ||
- pk1.isVarargs())) {
+ (pks[0].explicit() != pks[1].explicit() ||
+ pks[0].isVarargs())) {
errorExpected = true;
}
errorExpected |= pn == LambdaParameterName.UNDERSCORE &&
lk.arity() > 0;
- if (errorExpected != diagChecker.errorFound) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nFound error: " + diagChecker.errorFound +
+ if (errorExpected != res.hasErrors()) {
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
+ "\nFound error: " + res.hasErrors() +
"\nExpected error: " + errorExpected);
}
}
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- a/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,39 +23,39 @@
/*
* @test
- * @bug 7115052 8003280 8006694
+ * @bug 7115052 8003280 8006694 8129962
* @summary Add lambda tests
* Add parser support for method references
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm MethodReferenceParserTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main MethodReferenceParserTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import com.sun.source.util.JavacTask;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
+
+public class MethodReferenceParserTest extends ComboInstance<MethodReferenceParserTest> {
-public class MethodReferenceParserTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
-
- enum ReferenceKind {
- METHOD_REF("#Q::#Gm"),
- CONSTRUCTOR_REF("#Q::#Gnew"),
+ enum ReferenceKind implements ComboParameter {
+ METHOD_REF("#{QUAL}::#{TARGS}m"),
+ CONSTRUCTOR_REF("#{QUAL}::#{TARGS}new"),
FALSE_REF("min < max"),
- ERR_SUPER("#Q::#Gsuper"),
- ERR_METH0("#Q::#Gm()"),
- ERR_METH1("#Q::#Gm(X)"),
- ERR_CONSTR0("#Q::#Gnew()"),
- ERR_CONSTR1("#Q::#Gnew(X)");
+ ERR_SUPER("#{QUAL}::#{TARGS}super"),
+ ERR_METH0("#{QUAL}::#{TARGS}m()"),
+ ERR_METH1("#{QUAL}::#{TARGS}m(X)"),
+ ERR_CONSTR0("#{QUAL}::#{TARGS}new()"),
+ ERR_CONSTR1("#{QUAL}::#{TARGS}new(X)");
String referenceTemplate;
@@ -63,12 +63,6 @@
this.referenceTemplate = referenceTemplate;
}
- String getReferenceString(QualifierKind qk, GenericKind gk) {
- return referenceTemplate
- .replaceAll("#Q", qk.qualifier)
- .replaceAll("#G", gk.typeParameters);
- }
-
boolean erroneous() {
switch (this) {
case ERR_SUPER:
@@ -80,11 +74,16 @@
default: return false;
}
}
+
+ @Override
+ public String expand(String optParameter) {
+ return referenceTemplate;
+ }
}
- enum ContextKind {
- ASSIGN("SAM s = #E;"),
- METHOD("m(#E, i);");
+ enum ContextKind implements ComboParameter {
+ ASSIGN("SAM s = #{EXPR};"),
+ METHOD("m(#{EXPR}, i);");
String contextTemplate;
@@ -92,13 +91,13 @@
this.contextTemplate = contextTemplate;
}
- String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk,
- GenericKind gk, SubExprKind sk) {
- return contextTemplate.replaceAll("#E", ek.expressionString(rk, qk, gk, sk));
+ @Override
+ public String expand(String optParameter) {
+ return contextTemplate;
}
}
- enum GenericKind {
+ enum GenericKind implements ComboParameter {
NONE(""),
ONE("<X>"),
TWO("<X,Y>");
@@ -108,9 +107,14 @@
GenericKind(String typeParameters) {
this.typeParameters = typeParameters;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return typeParameters;
+ }
}
- enum QualifierKind {
+ enum QualifierKind implements ComboParameter {
THIS("this"),
SUPER("super"),
NEW("new Foo()"),
@@ -131,15 +135,20 @@
QualifierKind(String qualifier) {
this.qualifier = qualifier;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return qualifier;
+ }
}
- enum ExprKind {
- NONE("#R::S"),
- SINGLE_PAREN1("(#R#S)"),
- SINGLE_PAREN2("(#R)#S"),
- DOUBLE_PAREN1("((#R#S))"),
- DOUBLE_PAREN2("((#R)#S)"),
- DOUBLE_PAREN3("((#R))#S");
+ enum ExprKind implements ComboParameter {
+ NONE("#{MREF}"),
+ SINGLE_PAREN1("(#{MREF}#{SUBEXPR})"),
+ SINGLE_PAREN2("(#{MREF})#{SUBEXPR}"),
+ DOUBLE_PAREN1("((#{MREF}#{SUBEXPR}))"),
+ DOUBLE_PAREN2("((#{MREF})#{SUBEXPR})"),
+ DOUBLE_PAREN3("((#{MREF}))#{SUBEXPR}");
String expressionTemplate;
@@ -147,14 +156,13 @@
this.expressionTemplate = expressionTemplate;
}
- String expressionString(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) {
- return expressionTemplate
- .replaceAll("#R", rk.getReferenceString(qk, gk))
- .replaceAll("#S", sk.subExpression);
+ @Override
+ public String expand(String optParameter) {
+ return expressionTemplate;
}
}
- enum SubExprKind {
+ enum SubExprKind implements ComboParameter {
NONE(""),
SELECT_FIELD(".f"),
SELECT_METHOD(".f()"),
@@ -167,100 +175,45 @@
SubExprKind(String subExpression) {
this.subExpression = subExpression;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return subExpression;
+ }
}
public static void main(String... args) throws Exception {
- for (ReferenceKind rk : ReferenceKind.values()) {
- for (QualifierKind qk : QualifierKind.values()) {
- for (GenericKind gk : GenericKind.values()) {
- for (SubExprKind sk : SubExprKind.values()) {
- for (ExprKind ek : ExprKind.values()) {
- for (ContextKind ck : ContextKind.values()) {
- pool.execute(new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck));
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
+ new ComboTestHelper<MethodReferenceParserTest>()
+ .withDimension("MREF", (x, ref) -> x.rk = ref, ReferenceKind.values())
+ .withDimension("QUAL", QualifierKind.values())
+ .withDimension("TARGS", GenericKind.values())
+ .withDimension("EXPR", ExprKind.values())
+ .withDimension("SUBEXPR", SubExprKind.values())
+ .withDimension("CTX", ContextKind.values())
+ .run(MethodReferenceParserTest::new);
}
ReferenceKind rk;
- QualifierKind qk;
- GenericKind gk;
- SubExprKind sk;
- ExprKind ek;
- ContextKind ck;
- JavaSource source;
- DiagnosticChecker diagChecker;
- MethodReferenceParserTest(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk, ExprKind ek, ContextKind ck) {
- this.rk = rk;
- this.qk = qk;
- this.gk = gk;
- this.sk = sk;
- this.ek = ek;
- this.ck = ck;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
+ String template = "class Test {\n" +
+ " void test() {\n" +
+ " #{CTX}\n" +
+ " }" +
+ "}";
+
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withSourceFromTemplate(template)
+ .parse());
}
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "class Test {\n" +
- " void test() {\n" +
- " #C\n" +
- " }" +
- "}";
-
- String source;
-
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replaceAll("#C", ck.contextString(ek, rk, qk, gk, sk));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
- }
-
- @Override
- public void run() {
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
- null, null, Arrays.asList(source));
- try {
- ct.parse();
- } catch (Throwable ex) {
- processException(ex);
- return;
- }
- check();
- }
-
- void check() {
- checkCount.incrementAndGet();
-
- if (diagChecker.errorFound != rk.erroneous()) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nFound error: " + diagChecker.errorFound +
+ void check(Result<?> res) {
+ if (res.hasErrors() != rk.erroneous()) {
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
+ "\nFound error: " + res.hasErrors() +
"\nExpected error: " + rk.erroneous());
}
}
-
- static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
- }
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/TestBootstrapMethodsCount.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8129547
+ * @summary Excess entries in BootstrapMethods with the same (bsm, bsmKind, bsmStaticArgs), but different dynamicArgs
+ * @library /tools/javac/lib
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ */
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Locale;
+
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.source.util.TreeScanner;
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.BootstrapMethods_attribute;
+import com.sun.tools.classfile.ClassFile;
+
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Names;
+
+import static com.sun.tools.javac.jvm.ClassFile.*;
+
+public class TestBootstrapMethodsCount {
+
+ public static void main(String... args) throws Exception {
+ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+ new TestBootstrapMethodsCount().run(comp);
+ }
+
+ DiagChecker dc;
+
+ TestBootstrapMethodsCount() {
+ dc = new DiagChecker();
+ }
+
+ public void run(JavaCompiler comp) {
+ JavaSource source = new JavaSource();
+ JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, null, dc,
+ Arrays.asList("-g"), null, Arrays.asList(source));
+ Context context = ct.getContext();
+ Symtab syms = Symtab.instance(context);
+ Names names = Names.instance(context);
+ Types types = Types.instance(context);
+ ct.addTaskListener(new Indifier(syms, names, types));
+ try {
+ ct.generate();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new AssertionError(
+ String.format("Error thrown when compiling following code\n%s",
+ source.source));
+ }
+ if (dc.diagFound) {
+ throw new AssertionError(
+ String.format("Diags found when compiling following code\n%s\n\n%s",
+ source.source, dc.printDiags()));
+ }
+ verifyBytecode();
+ }
+
+ void verifyBytecode() {
+ File compiledTest = new File("Test.class");
+ try {
+ ClassFile cf = ClassFile.read(compiledTest);
+ BootstrapMethods_attribute bsm_attr =
+ (BootstrapMethods_attribute)cf
+ .getAttribute(Attribute.BootstrapMethods);
+ int length = bsm_attr.bootstrap_method_specifiers.length;
+ if (length != 1) {
+ throw new Error("Bad number of method specifiers " +
+ "in BootstrapMethods attribute: " + length);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("error reading " + compiledTest +": " + e);
+ }
+ }
+
+ class JavaSource extends SimpleJavaFileObject {
+
+ static final String source = "import java.lang.invoke.*;\n" +
+ "class Bootstrap {\n" +
+ " public static CallSite bsm(MethodHandles.Lookup lookup, " +
+ "String name, MethodType methodType) {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n" +
+ "class Test {\n" +
+ " void m1() { }\n" +
+ " void m2(Object arg1) { }\n" +
+ " void test1() {\n" +
+ " Object o = this; // marker statement \n" +
+ " m1();\n" +
+ " }\n" +
+ " void test2(Object arg1) {\n" +
+ " Object o = this; // marker statement \n" +
+ " m2(arg1);\n" +
+ " }\n" +
+ "}";
+
+ JavaSource() {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+ }
+
+ class Indifier extends TreeScanner<Void, Void> implements TaskListener {
+
+ MethodSymbol bsm;
+ Symtab syms;
+ Names names;
+ Types types;
+
+ Indifier(Symtab syms, Names names, Types types) {
+ this.syms = syms;
+ this.names = names;
+ this.types = types;
+ }
+
+ @Override
+ public void started(TaskEvent e) {
+ //do nothing
+ }
+
+ @Override
+ public void finished(TaskEvent e) {
+ if (e.getKind() == TaskEvent.Kind.ANALYZE) {
+ scan(e.getCompilationUnit(), null);
+ }
+ }
+
+ @Override
+ public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
+ super.visitMethodInvocation(node, p);
+ JCMethodInvocation apply = (JCMethodInvocation)node;
+ JCIdent ident = (JCIdent)apply.meth;
+ Symbol oldSym = ident.sym;
+ if (!oldSym.isConstructor()) {
+ ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
+ oldSym.owner, REF_invokeStatic, bsm, oldSym.type, new Object[0]);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitMethod(MethodTree node, Void p) {
+ super.visitMethod(node, p);
+ if (node.getName().toString().equals("bsm")) {
+ bsm = ((JCMethodDecl)node).sym;
+ }
+ return null;
+ }
+ }
+
+ static class DiagChecker
+ implements javax.tools.DiagnosticListener<JavaFileObject> {
+
+ boolean diagFound;
+ ArrayList<String> diags = new ArrayList<>();
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ diags.add(diagnostic.getMessage(Locale.getDefault()));
+ diagFound = true;
+ }
+
+ String printDiags() {
+ StringBuilder buf = new StringBuilder();
+ for (String s : diags) {
+ buf.append(s);
+ buf.append("\n");
+ }
+ return buf.toString();
+ }
+ }
+
+}
--- a/langtools/test/tools/javac/lambda/TestInvokeDynamic.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/lambda/TestInvokeDynamic.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,33 +23,27 @@
/*
* @test
- * @bug 7194586 8003280 8006694 8010404
+ * @bug 7194586 8003280 8006694 8010404 8129962
* @summary Add lambda tests
* Add back-end support for invokedynamic
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../lib
+ * @library /tools/javac/lib
* @modules jdk.jdeps/com.sun.tools.classfile
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
* jdk.compiler/com.sun.tools.javac.jvm
* jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm TestInvokeDynamic
+ * @build combo.ComboTestHelper
+ * @run main TestInvokeDynamic
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import java.io.IOException;
+import java.io.InputStream;
-import java.io.File;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Locale;
-
-import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
@@ -78,13 +72,17 @@
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Names;
+import combo.ComboParameter;
+import combo.ComboTask;
+import combo.ComboTestHelper;
+import combo.ComboInstance;
+import combo.ComboTask.Result;
+
import static com.sun.tools.javac.jvm.ClassFile.*;
-public class TestInvokeDynamic
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+public class TestInvokeDynamic extends ComboInstance<TestInvokeDynamic> {
- enum StaticArgumentKind {
+ enum StaticArgumentKind implements ComboParameter {
STRING("Hello!", "String", "Ljava/lang/String;") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
@@ -189,88 +187,91 @@
throw new AssertionError();
}
}
+
+ @Override
+ public String expand(String optParameter) {
+ return sourceTypeStr;
+ }
}
- enum StaticArgumentsArity {
- ZERO(0),
- ONE(1),
- TWO(2),
- THREE(3);
+ enum StaticArgumentsArity implements ComboParameter {
+ ZERO(0, ""),
+ ONE(1, ",#{SARG[0]} s1"),
+ TWO(2, ",#{SARG[0]} s1, #{SARG[1]} s2"),
+ THREE(3, ",#{SARG[0]} s1, #{SARG[1]} s2, #{SARG[2]} s3");
int arity;
+ String argsTemplate;
- StaticArgumentsArity(int arity) {
+ StaticArgumentsArity(int arity, String argsTemplate) {
this.arity = arity;
+ this.argsTemplate = argsTemplate;
+ }
+
+ @Override
+ public String expand(String optParameter) {
+ return argsTemplate;
}
}
public static void main(String... args) throws Exception {
- for (StaticArgumentsArity arity : StaticArgumentsArity.values()) {
- if (arity.arity == 0) {
- pool.execute(new TestInvokeDynamic(arity));
- } else {
- for (StaticArgumentKind sak1 : StaticArgumentKind.values()) {
- if (arity.arity == 1) {
- pool.execute(new TestInvokeDynamic(arity, sak1));
- } else {
- for (StaticArgumentKind sak2 : StaticArgumentKind.values()) {
- if (arity.arity == 2) {
- pool.execute(new TestInvokeDynamic(arity, sak1, sak2));
- } else {
- for (StaticArgumentKind sak3 : StaticArgumentKind.values()) {
- pool.execute(
- new TestInvokeDynamic(arity, sak1, sak2, sak3));
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
+ new ComboTestHelper<TestInvokeDynamic>()
+ .withFilter(TestInvokeDynamic::redundantTestFilter)
+ .withDimension("SARGS", (x, arity) -> x.arity = arity, StaticArgumentsArity.values())
+ .withArrayDimension("SARG", (x, arg, idx) -> x.saks[idx] = arg, 3, StaticArgumentKind.values())
+ .run(TestInvokeDynamic::new);
}
StaticArgumentsArity arity;
- StaticArgumentKind[] saks;
- DiagChecker dc;
+ StaticArgumentKind[] saks = new StaticArgumentKind[3];
- TestInvokeDynamic(StaticArgumentsArity arity, StaticArgumentKind... saks) {
- this.arity = arity;
- this.saks = saks;
- dc = new DiagChecker();
+ boolean redundantTestFilter() {
+ for (int i = arity.arity ; i < saks.length ; i++) {
+ if (saks[i].ordinal() != 0) {
+ return false;
+ }
+ }
+ return true;
}
- public void run() {
- int id = checkCount.incrementAndGet();
- JavaSource source = new JavaSource(id);
- JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc,
- Arrays.asList("-g"), null, Arrays.asList(source));
+ final String source_template =
+ "import java.lang.invoke.*;\n" +
+ "class Test {\n" +
+ " void m() { }\n" +
+ " void test() {\n" +
+ " Object o = this; // marker statement \n" +
+ " m();\n" +
+ " }\n" +
+ "}\n" +
+ "class Bootstrap {\n" +
+ " public static CallSite bsm(MethodHandles.Lookup lookup, " +
+ "String name, MethodType methodType #{SARGS}) {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}";
+
+ @Override
+ public void doWork() throws IOException {
+ ComboTask comboTask = newCompilationTask()
+ .withOption("-g")
+ .withSourceFromTemplate(source_template);
+
+ JavacTaskImpl ct = (JavacTaskImpl)comboTask.getTask();
Context context = ct.getContext();
Symtab syms = Symtab.instance(context);
Names names = Names.instance(context);
Types types = Types.instance(context);
ct.addTaskListener(new Indifier(syms, names, types));
- try {
- ct.generate();
- } catch (Throwable t) {
- t.printStackTrace();
- throw new AssertionError(
- String.format("Error thrown when compiling following code\n%s",
- source.source));
- }
- if (dc.diagFound) {
- throw new AssertionError(
- String.format("Diags found when compiling following code\n%s\n\n%s",
- source.source, dc.printDiags()));
- }
- verifyBytecode(id);
+ verifyBytecode(comboTask.generate());
}
- void verifyBytecode(int id) {
- File compiledTest = new File(String.format("Test%d.class", id));
- try {
- ClassFile cf = ClassFile.read(compiledTest);
+ void verifyBytecode(Result<Iterable<? extends JavaFileObject>> res) {
+ if (res.hasErrors()) {
+ fail("Diags found when compiling instance: " + res.compilationInfo());
+ return;
+ }
+ try (InputStream is = res.get().iterator().next().openInputStream()){
+ ClassFile cf = ClassFile.read(is);
Method testMethod = null;
for (Method m : cf.methods) {
if (m.getName(cf.constant_pool).equals("test")) {
@@ -279,12 +280,14 @@
}
}
if (testMethod == null) {
- throw new Error("Test method not found");
+ fail("Test method not found");
+ return;
}
Code_attribute ea =
(Code_attribute)testMethod.attributes.get(Attribute.Code);
if (testMethod == null) {
- throw new Error("Code attribute for test() method not found");
+ fail("Code attribute for test() method not found");
+ return;
}
int bsmIdx = -1;
@@ -296,37 +299,39 @@
.constant_pool.get(i.getShort(1));
bsmIdx = indyInfo.bootstrap_method_attr_index;
if (!indyInfo.getNameAndTypeInfo().getType().equals("()V")) {
- throw new
- AssertionError("type mismatch for CONSTANT_InvokeDynamic_info");
+ fail("type mismatch for CONSTANT_InvokeDynamic_info");
+ return;
}
}
}
if (bsmIdx == -1) {
- throw new Error("Missing invokedynamic in generated code");
+ fail("Missing invokedynamic in generated code");
+ return;
}
BootstrapMethods_attribute bsm_attr =
(BootstrapMethods_attribute)cf
.getAttribute(Attribute.BootstrapMethods);
if (bsm_attr.bootstrap_method_specifiers.length != 1) {
- throw new Error("Bad number of method specifiers " +
+ fail("Bad number of method specifiers " +
"in BootstrapMethods attribute");
+ return;
}
BootstrapMethods_attribute.BootstrapMethodSpecifier bsm_spec =
bsm_attr.bootstrap_method_specifiers[0];
if (bsm_spec.bootstrap_arguments.length != arity.arity) {
- throw new Error("Bad number of static invokedynamic args " +
+ fail("Bad number of static invokedynamic args " +
"in BootstrapMethod attribute");
+ return;
}
- int count = 0;
- for (StaticArgumentKind sak : saks) {
- if (!sak.check(cf.constant_pool
- .get(bsm_spec.bootstrap_arguments[count]))) {
- throw new Error("Bad static argument value " + sak);
+ for (int i = 0 ; i < arity.arity ; i++) {
+ if (!saks[i].check(cf.constant_pool
+ .get(bsm_spec.bootstrap_arguments[i]))) {
+ fail("Bad static argument value " + saks[i]);
+ return;
}
- count++;
}
CONSTANT_MethodHandle_info bsm_handle =
@@ -334,7 +339,8 @@
.get(bsm_spec.bootstrap_method_ref);
if (bsm_handle.reference_kind != RefKind.REF_invokeStatic) {
- throw new Error("Bad kind on boostrap method handle");
+ fail("Bad kind on boostrap method handle");
+ return;
}
CONSTANT_Methodref_info bsm_ref =
@@ -342,88 +348,51 @@
.get(bsm_handle.reference_index);
if (!bsm_ref.getClassInfo().getName().equals("Bootstrap")) {
- throw new Error("Bad owner of boostrap method");
+ fail("Bad owner of boostrap method");
+ return;
}
if (!bsm_ref.getNameAndTypeInfo().getName().equals("bsm")) {
- throw new Error("Bad boostrap method name");
+ fail("Bad boostrap method name");
+ return;
}
if (!bsm_ref.getNameAndTypeInfo()
.getType().equals(asBSMSignatureString())) {
- throw new Error("Bad boostrap method type" +
+ fail("Bad boostrap method type" +
bsm_ref.getNameAndTypeInfo().getType() + " " +
asBSMSignatureString());
+ return;
}
LineNumberTable_attribute lnt =
(LineNumberTable_attribute)ea.attributes.get(Attribute.LineNumberTable);
if (lnt == null) {
- throw new Error("No LineNumberTable attribute");
+ fail("No LineNumberTable attribute");
+ return;
}
if (lnt.line_number_table_length != 3) {
- throw new Error("Wrong number of entries in LineNumberTable");
+ fail("Wrong number of entries in LineNumberTable");
+ return;
}
} catch (Exception e) {
e.printStackTrace();
- throw new Error("error reading " + compiledTest +": " + e);
+ fail("error reading classfile: " + res.compilationInfo());
+ return;
}
}
String asBSMSignatureString() {
StringBuilder buf = new StringBuilder();
buf.append("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;");
- for (StaticArgumentKind sak : saks) {
- buf.append(sak.bytecodeTypeStr);
+ for (int i = 0 ; i < arity.arity ; i++) {
+ buf.append(saks[i].bytecodeTypeStr);
}
buf.append(")Ljava/lang/invoke/CallSite;");
return buf.toString();
}
- class JavaSource extends SimpleJavaFileObject {
-
- static final String source_template = "import java.lang.invoke.*;\n" +
- "class Bootstrap {\n" +
- " public static CallSite bsm(MethodHandles.Lookup lookup, " +
- "String name, MethodType methodType #SARGS) {\n" +
- " return null;\n" +
- " }\n" +
- "}\n" +
- "class Test#ID {\n" +
- " void m() { }\n" +
- " void test() {\n" +
- " Object o = this; // marker statement \n" +
- " m();\n" +
- " }\n" +
- "}";
-
- String source;
-
- JavaSource(int id) {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = source_template.replace("#SARGS", asSignatureString())
- .replace("#ID", String.valueOf(id));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
-
- String asSignatureString() {
- int count = 0;
- StringBuilder buf = new StringBuilder();
- for (StaticArgumentKind sak : saks) {
- buf.append(",");
- buf.append(sak.sourceTypeStr);
- buf.append(' ');
- buf.append(String.format("x%d", count++));
- }
- return buf.toString();
- }
- }
-
class Indifier extends TreeScanner<Void, Void> implements TaskListener {
MethodSymbol bsm;
@@ -475,26 +444,4 @@
return null;
}
}
-
- static class DiagChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean diagFound;
- ArrayList<String> diags = new ArrayList<>();
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- diags.add(diagnostic.getMessage(Locale.getDefault()));
- diagFound = true;
- }
-
- String printDiags() {
- StringBuilder buf = new StringBuilder();
- for (String s : diags) {
- buf.append(s);
- buf.append("\n");
- }
- return buf.toString();
- }
- }
-
}
--- a/langtools/test/tools/javac/lambda/TestLambdaToMethodStats.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/lambda/TestLambdaToMethodStats.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,34 +23,35 @@
/*
* @test
- * @bug 8013576
+ * @bug 8013576 8129962
* @summary Add stat support to LambdaToMethod
- * @library ../lib
+ * @library /tools/javac/lib
* @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm TestLambdaToMethodStats
+ * @build combo.ComboTestHelper
+ * @run main TestLambdaToMethodStats
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
-import java.net.URI;
-import java.util.Arrays;
+import java.io.IOException;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.ClientCodeWrapper;
-import com.sun.tools.javac.util.JCDiagnostic;
-public class TestLambdaToMethodStats
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+import com.sun.tools.javac.util.List;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
- enum ExprKind {
+public class TestLambdaToMethodStats extends ComboInstance<TestLambdaToMethodStats> {
+
+ enum ExprKind implements ComboParameter {
LAMBDA("()->null"),
MREF1("this::g"),
MREF2("this::h");
@@ -60,9 +61,14 @@
ExprKind(String exprStr) {
this.exprStr = exprStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return exprStr;
+ }
}
- enum TargetKind {
+ enum TargetKind implements ComboParameter {
IMPLICIT(""),
SERIALIZABLE("(A & java.io.Serializable)");
@@ -71,124 +77,89 @@
TargetKind(String targetStr) {
this.targetStr = targetStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return targetStr;
+ }
+ }
+
+ enum DiagnosticKind {
+ LAMBDA_STAT("compiler.note.lambda.stat", true, false),
+ MREF_STAT("compiler.note.mref.stat", false, false),
+ MREF_STAT1("compiler.note.mref.stat.1", false, true);
+
+ String code;
+ boolean lambda;
+ boolean bridge;
+
+ DiagnosticKind(String code, boolean lambda, boolean bridge) {
+ this.code = code;
+ this.lambda = lambda;
+ this.bridge = bridge;
+ }
}
public static void main(String... args) throws Exception {
- for (ExprKind ek : ExprKind.values()) {
- for (TargetKind tk : TargetKind.values()) {
- pool.execute(new TestLambdaToMethodStats(ek, tk));
- }
- }
-
- checkAfterExec(true);
+ new ComboTestHelper<TestLambdaToMethodStats>()
+ .withDimension("EXPR", (x, expr) -> x.ek = expr, ExprKind.values())
+ .withDimension("CAST", (x, target) -> x.tk = target, TargetKind.values())
+ .run(TestLambdaToMethodStats::new);
}
ExprKind ek;
TargetKind tk;
- JavaSource source;
- DiagnosticChecker diagChecker;
-
- TestLambdaToMethodStats(ExprKind ek, TargetKind tk) {
- this.ek = ek;
- this.tk = tk;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
+ String template = "interface A {\n" +
+ " Object o();\n" +
+ "}\n" +
+ "class Test {\n" +
+ " A a = #{CAST}#{EXPR};\n" +
+ " Object g() { return null; }\n" +
+ " Object h(Object... o) { return null; }\n" +
+ "}";
+
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withOption("-XDdumpLambdaToMethodStats")
+ .withSourceFromTemplate(template)
+ .generate());
}
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "interface A {\n" +
- " Object o();\n" +
- "}\n" +
- "class Test {\n" +
- " A a = #C#E;\n" +
- " Object g() { return null; }\n" +
- " Object h(Object... o) { return null; }\n" +
- "}";
-
- String source;
-
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replaceAll("#E", ek.exprStr)
- .replaceAll("#C", tk.targetStr);
+ void check(Result<?> res) {
+ DiagnosticKind diag = null;
+ boolean altMetafactory = false;
+ for (DiagnosticKind dk : DiagnosticKind.values()) {
+ List<Diagnostic<? extends JavaFileObject>> jcDiag = res.diagnosticsForKey(dk.code);
+ if (jcDiag.nonEmpty()) {
+ diag = dk;
+ ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
+ (ClientCodeWrapper.DiagnosticSourceUnwrapper)jcDiag.head;
+ altMetafactory = (Boolean)dsu.d.getArgs()[0];
+ break;
+ }
}
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
+ if (diag == null) {
+ fail("No diagnostic found; " + res.compilationInfo());
}
- }
- public void run() {
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
- Arrays.asList("-XDdumpLambdaToMethodStats"),
- null, Arrays.asList(source));
- try {
- ct.generate();
- } catch (Throwable ex) {
- throw new
- AssertionError("Error thron when analyzing the following source:\n" +
- source.getCharContent(true));
- }
- check();
- }
-
- void check() {
- checkCount.incrementAndGet();
-
- boolean error = diagChecker.lambda !=
+ boolean error = diag.lambda !=
(ek == ExprKind.LAMBDA);
- error |= diagChecker.bridge !=
+ error |= diag.bridge !=
(ek == ExprKind.MREF2);
- error |= diagChecker.altMetafactory !=
+ error |= altMetafactory !=
(tk == TargetKind.SERIALIZABLE);
if (error) {
- throw new AssertionError("Bad stat diagnostic found for source\n" +
- "lambda = " + diagChecker.lambda + "\n" +
- "bridge = " + diagChecker.bridge + "\n" +
- "altMF = " + diagChecker.altMetafactory + "\n" +
- source.source);
- }
- }
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean altMetafactory;
- boolean bridge;
- boolean lambda;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- try {
- if (diagnostic.getKind() == Diagnostic.Kind.NOTE) {
- switch (diagnostic.getCode()) {
- case "compiler.note.lambda.stat":
- lambda = true;
- break;
- case "compiler.note.mref.stat":
- lambda = false;
- bridge = false;
- break;
- case "compiler.note.mref.stat.1":
- lambda = false;
- bridge = true;
- break;
- default:
- throw new AssertionError("unexpected note: " + diagnostic.getCode());
- }
- ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
- (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic;
- altMetafactory = (Boolean)dsu.d.getArgs()[0];
- }
- } catch (RuntimeException t) {
- t.printStackTrace();
- throw t;
- }
+ fail("Bad stat diagnostic found for source\n" +
+ "lambda = " + diag.lambda + "\n" +
+ "bridge = " + diag.bridge + "\n" +
+ "altMF = " + altMetafactory + "\n" +
+ res.compilationInfo());
}
}
}
--- a/langtools/test/tools/javac/lambda/bytecode/TestLambdaBytecode.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/lambda/bytecode/TestLambdaBytecode.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,18 +23,20 @@
/*
* @test
- * @bug 8009649
+ * @bug 8009649 8129962
* @summary Lambda back-end should generate invokespecial for method handles referring to private instance methods
- * @library ../../lib
+ * @library /tools/javac/lib
* @modules jdk.jdeps/com.sun.tools.classfile
* jdk.compiler/com.sun.tools.javac.api
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm TestLambdaBytecode
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main TestLambdaBytecode
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.BootstrapMethods_attribute;
import com.sun.tools.classfile.ClassFile;
@@ -43,26 +45,22 @@
import com.sun.tools.classfile.Instruction;
import com.sun.tools.classfile.Method;
-import com.sun.tools.javac.api.JavacTaskImpl;
-
+import java.io.IOException;
+import java.io.InputStream;
-import java.io.File;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Locale;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
-import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import static com.sun.tools.javac.jvm.ClassFile.*;
+public class TestLambdaBytecode extends ComboInstance<TestLambdaBytecode> {
-public class TestLambdaBytecode
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+ static final int MF_ARITY = 3;
+ static final String MH_SIG = "()V";
- enum ClassKind {
+ enum ClassKind implements ComboParameter {
CLASS("class"),
INTERFACE("interface");
@@ -71,9 +69,14 @@
ClassKind(String classStr) {
this.classStr = classStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return classStr;
+ }
}
- enum AccessKind {
+ enum AccessKind implements ComboParameter {
PUBLIC("public"),
PRIVATE("private");
@@ -82,9 +85,14 @@
AccessKind(String accessStr) {
this.accessStr = accessStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return accessStr;
+ }
}
- enum StaticKind {
+ enum StaticKind implements ComboParameter {
STATIC("static"),
INSTANCE("");
@@ -93,9 +101,14 @@
StaticKind(String staticStr) {
this.staticStr = staticStr;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return staticStr;
+ }
}
- enum DefaultKind {
+ enum DefaultKind implements ComboParameter {
DEFAULT("default"),
NO_DEFAULT("");
@@ -104,15 +117,10 @@
DefaultKind(String defaultStr) {
this.defaultStr = defaultStr;
}
- }
- enum ExprKind {
- LAMBDA("Runnable r = ()->{ target(); };");
-
- String exprString;
-
- ExprKind(String exprString) {
- this.exprString = exprString;
+ @Override
+ public String expand(String optParameter) {
+ return defaultStr;
}
}
@@ -155,83 +163,53 @@
return true;
}
}
-
- String mods() {
- StringBuilder buf = new StringBuilder();
- buf.append(ak.accessStr);
- buf.append(' ');
- buf.append(sk.staticStr);
- buf.append(' ');
- buf.append(dk.defaultStr);
- return buf.toString();
- }
}
public static void main(String... args) throws Exception {
- for (ClassKind ck : ClassKind.values()) {
- for (AccessKind ak1 : AccessKind.values()) {
- for (StaticKind sk1 : StaticKind.values()) {
- for (DefaultKind dk1 : DefaultKind.values()) {
- for (AccessKind ak2 : AccessKind.values()) {
- for (StaticKind sk2 : StaticKind.values()) {
- for (DefaultKind dk2 : DefaultKind.values()) {
- for (ExprKind ek : ExprKind.values()) {
- pool.execute(new TestLambdaBytecode(ck, ak1, ak2, sk1, sk2, dk1, dk2, ek));
- }
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
+ new ComboTestHelper<TestLambdaBytecode>()
+ .withDimension("CLASSKIND", (x, ck) -> x.ck = ck, ClassKind.values())
+ .withArrayDimension("ACCESS", (x, acc, idx) -> x.accessKinds[idx] = acc, 2, AccessKind.values())
+ .withArrayDimension("STATIC", (x, sk, idx) -> x.staticKinds[idx] = sk, 2, StaticKind.values())
+ .withArrayDimension("DEFAULT", (x, dk, idx) -> x.defaultKinds[idx] = dk, 2, DefaultKind.values())
+ .run(TestLambdaBytecode::new, TestLambdaBytecode::init);
}
+ ClassKind ck;
+ AccessKind[] accessKinds = new AccessKind[2];
+ StaticKind[] staticKinds = new StaticKind[2];
+ DefaultKind[] defaultKinds = new DefaultKind[2];
MethodKind mk1, mk2;
- ExprKind ek;
- DiagChecker dc;
- TestLambdaBytecode(ClassKind ck, AccessKind ak1, AccessKind ak2, StaticKind sk1,
- StaticKind sk2, DefaultKind dk1, DefaultKind dk2, ExprKind ek) {
- mk1 = new MethodKind(ck, ak1, sk1, dk1);
- mk2 = new MethodKind(ck, ak2, sk2, dk2);
- this.ek = ek;
- dc = new DiagChecker();
+ void init() {
+ mk1 = new MethodKind(ck, accessKinds[0], staticKinds[0], defaultKinds[0]);
+ mk2 = new MethodKind(ck, accessKinds[1], staticKinds[1], defaultKinds[1]);
}
- public void run() {
- int id = checkCount.incrementAndGet();
- JavaSource source = new JavaSource(id);
- JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc,
- null, null, Arrays.asList(source));
- try {
- ct.generate();
- } catch (Throwable t) {
- t.printStackTrace();
- throw new AssertionError(
- String.format("Error thrown when compiling following code\n%s",
- source.source));
- }
- if (dc.diagFound) {
+ String source_template =
+ "#{CLASSKIND} Test {\n" +
+ " #{ACCESS[0]} #{STATIC[0]} #{DEFAULT[0]} void test() { Runnable r = ()->{ target(); }; }\n" +
+ " #{ACCESS[1]} #{STATIC[1]} #{DEFAULT[1]} void target() { }\n" +
+ "}\n";
+
+ @Override
+ public void doWork() throws IOException {
+ verifyBytecode(newCompilationTask()
+ .withSourceFromTemplate(source_template)
+ .generate());
+ }
+
+ void verifyBytecode(Result<Iterable<? extends JavaFileObject>> res) {
+ if (res.hasErrors()) {
boolean errorExpected = !mk1.isOK() || !mk2.isOK();
errorExpected |= mk1.isStatic() && !mk2.isStatic();
if (!errorExpected) {
- throw new AssertionError(
- String.format("Diags found when compiling following code\n%s\n\n%s",
- source.source, dc.printDiags()));
+ fail("Diags found when compiling instance; " + res.compilationInfo());
}
return;
}
- verifyBytecode(id, source);
- }
-
- void verifyBytecode(int id, JavaSource source) {
- File compiledTest = new File(String.format("Test%d.class", id));
- try {
- ClassFile cf = ClassFile.read(compiledTest);
+ try (InputStream is = res.get().iterator().next().openInputStream()) {
+ ClassFile cf = ClassFile.read(is);
Method testMethod = null;
for (Method m : cf.methods) {
if (m.getName(cf.constant_pool).equals("test")) {
@@ -240,12 +218,14 @@
}
}
if (testMethod == null) {
- throw new Error("Test method not found");
+ fail("Test method not found");
+ return;
}
Code_attribute ea =
(Code_attribute)testMethod.attributes.get(Attribute.Code);
if (testMethod == null) {
- throw new Error("Code attribute for test() method not found");
+ fail("Code attribute for test() method not found");
+ return;
}
int bsmIdx = -1;
@@ -256,29 +236,34 @@
(CONSTANT_InvokeDynamic_info)cf
.constant_pool.get(i.getShort(1));
bsmIdx = indyInfo.bootstrap_method_attr_index;
- if (!indyInfo.getNameAndTypeInfo().getType().equals(makeIndyType(id))) {
- throw new
- AssertionError("type mismatch for CONSTANT_InvokeDynamic_info " + source.source + "\n" + indyInfo.getNameAndTypeInfo().getType() + "\n" + makeIndyType(id));
+ if (!indyInfo.getNameAndTypeInfo().getType().equals(makeIndyType())) {
+ fail("type mismatch for CONSTANT_InvokeDynamic_info " +
+ res.compilationInfo() + "\n" + indyInfo.getNameAndTypeInfo().getType() +
+ "\n" + makeIndyType());
+ return;
}
}
}
if (bsmIdx == -1) {
- throw new Error("Missing invokedynamic in generated code");
+ fail("Missing invokedynamic in generated code");
+ return;
}
BootstrapMethods_attribute bsm_attr =
(BootstrapMethods_attribute)cf
.getAttribute(Attribute.BootstrapMethods);
if (bsm_attr.bootstrap_method_specifiers.length != 1) {
- throw new Error("Bad number of method specifiers " +
+ fail("Bad number of method specifiers " +
"in BootstrapMethods attribute");
+ return;
}
BootstrapMethods_attribute.BootstrapMethodSpecifier bsm_spec =
bsm_attr.bootstrap_method_specifiers[0];
if (bsm_spec.bootstrap_arguments.length != MF_ARITY) {
- throw new Error("Bad number of static invokedynamic args " +
+ fail("Bad number of static invokedynamic args " +
"in BootstrapMethod attribute");
+ return;
}
CONSTANT_MethodHandle_info mh =
@@ -294,74 +279,27 @@
}
if (!kindOK) {
- throw new Error("Bad invoke kind in implementation method handle");
+ fail("Bad invoke kind in implementation method handle");
+ return;
}
if (!mh.getCPRefInfo().getNameAndTypeInfo().getType().toString().equals(MH_SIG)) {
- throw new Error("Type mismatch in implementation method handle");
+ fail("Type mismatch in implementation method handle");
+ return;
}
} catch (Exception e) {
e.printStackTrace();
- throw new Error("error reading " + compiledTest +": " + e);
+ fail("error reading " + res.compilationInfo() + ": " + e);
}
}
- String makeIndyType(int id) {
+
+ String makeIndyType() {
StringBuilder buf = new StringBuilder();
buf.append("(");
if (!mk2.isStatic()) {
- buf.append(String.format("LTest%d;", id));
+ buf.append("LTest;");
}
buf.append(")Ljava/lang/Runnable;");
return buf.toString();
}
-
- static final int MF_ARITY = 3;
- static final String MH_SIG = "()V";
-
- class JavaSource extends SimpleJavaFileObject {
-
- static final String source_template =
- "#CK Test#ID {\n" +
- " #MOD1 void test() { #EK }\n" +
- " #MOD2 void target() { }\n" +
- "}\n";
-
- String source;
-
- JavaSource(int id) {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = source_template.replace("#CK", mk1.ck.classStr)
- .replace("#MOD1", mk1.mods())
- .replace("#MOD2", mk2.mods())
- .replace("#EK", ek.exprString)
- .replace("#ID", String.valueOf(id));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
- }
-
- static class DiagChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean diagFound;
- ArrayList<String> diags = new ArrayList<>();
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- diags.add(diagnostic.getMessage(Locale.getDefault()));
- diagFound = true;
- }
-
- String printDiags() {
- StringBuilder buf = new StringBuilder();
- for (String s : diags) {
- buf.append(s);
- buf.append("\n");
- }
- return buf.toString();
- }
- }
-
}
--- a/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,34 +23,36 @@
/*
* @test
- * @bug 8003280 8006694
+ * @bug 8003280 8006694 8129962
* @summary Add lambda tests
* Automatic test for checking correctness of structural most specific test routine
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../../lib
+ * @library /tools/javac/lib
* @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm/timeout=600 StructuralMostSpecificTest
+ * @build combo.ComboTestHelper
+
+ * @run main StructuralMostSpecificTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
-import java.net.URI;
-import java.util.Arrays;
+import javax.lang.model.element.Element;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.ClientCodeWrapper;
import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.List;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
-public class StructuralMostSpecificTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+public class StructuralMostSpecificTest extends ComboInstance<StructuralMostSpecificTest> {
- enum RetTypeKind {
+ enum RetTypeKind implements ComboParameter {
SHORT("short"),
INT("int"),
OBJECT("Object"),
@@ -76,9 +78,13 @@
/* INTEGER */ { false , false , true , true , false , false },
/* VOID */ { false , false , false , false , true , true },
/* J_L_VOID */{ false , false , true , false , false , true } };
+
+ public String expand(String optParameter) {
+ return retTypeStr;
+ }
}
- enum ArgTypeKind {
+ enum ArgTypeKind implements ComboParameter {
SHORT("short"),
INT("int"),
BOOLEAN("boolean"),
@@ -91,9 +97,13 @@
ArgTypeKind(String typeStr) {
this.argTypeStr = typeStr;
}
+
+ public String expand(String optParameter) {
+ return argTypeStr;
+ }
}
- enum ExceptionKind {
+ enum ExceptionKind implements ComboParameter {
NONE(""),
EXCEPTION("throws Exception"),
SQL_EXCEPTION("throws java.sql.SQLException"),
@@ -104,9 +114,13 @@
ExceptionKind(String exceptionStr) {
this.exceptionStr = exceptionStr;
}
+
+ public String expand(String optParameter) {
+ return exceptionStr;
+ }
}
- enum LambdaReturnKind {
+ enum LambdaReturnKind implements ComboParameter {
VOID("return;"),
SHORT("return (short)0;"),
INT("return 0;"),
@@ -144,118 +158,72 @@
/* INTEGER */ { false , false , true , false , false },
/* VOID */ { false , false , false , false , false },
/* J_L_VOID */{ true , false , false , false , false } };
- }
- public static void main(String... args) throws Exception {
- for (LambdaReturnKind lrk : LambdaReturnKind.values()) {
- for (RetTypeKind rk1 : RetTypeKind.values()) {
- for (RetTypeKind rk2 : RetTypeKind.values()) {
- for (ExceptionKind ek1 : ExceptionKind.values()) {
- for (ExceptionKind ek2 : ExceptionKind.values()) {
- for (ArgTypeKind ak11 : ArgTypeKind.values()) {
- for (ArgTypeKind ak12 : ArgTypeKind.values()) {
- pool.execute(
- new StructuralMostSpecificTest(lrk, rk1,
- rk2, ek1, ek2, ak11, ak12));
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
- }
-
- LambdaReturnKind lrk;
- RetTypeKind rt1, rt2;
- ArgTypeKind ak1, ak2;
- ExceptionKind ek1, ek2;
- JavaSource source;
- DiagnosticChecker diagChecker;
-
- StructuralMostSpecificTest(LambdaReturnKind lrk, RetTypeKind rt1, RetTypeKind rt2,
- ExceptionKind ek1, ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) {
- this.lrk = lrk;
- this.rt1 = rt1;
- this.rt2 = rt2;
- this.ek1 = ek1;
- this.ek2 = ek2;
- this.ak1 = ak1;
- this.ak2 = ak2;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
- }
-
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "interface SAM1 {\n" +
- " #R1 m(#A1 a1) #E1;\n" +
- "}\n" +
- "interface SAM2 {\n" +
- " #R2 m(#A2 a1) #E2;\n" +
- "}\n" +
- "class Test {\n" +
- " void m(SAM1 s) { }\n" +
- " void m(SAM2 s) { }\n" +
- " { m((#A1 x)->{ #LR }); }\n" +
- "}\n";
-
- String source;
-
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replaceAll("#LR", lrk.retStr)
- .replaceAll("#R1", rt1.retTypeStr)
- .replaceAll("#R2", rt2.retTypeStr)
- .replaceAll("#A1", ak1.argTypeStr)
- .replaceAll("#A2", ak2.argTypeStr)
- .replaceAll("#E1", ek1.exceptionStr)
- .replaceAll("#E2", ek2.exceptionStr);
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
+ public String expand(String optParameter) {
+ return retStr;
}
}
- public void run() {
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
- Arrays.asList("-XDverboseResolution=all,-predef,-internal,-object-init"),
- null, Arrays.asList(source));
- try {
- ct.analyze();
- } catch (Throwable ex) {
- throw new
- AssertionError("Error thron when analyzing the following source:\n" +
- source.getCharContent(true));
- }
- check();
+ static final String sourceTemplate =
+ "interface SAM1 {\n" +
+ " #{RET[0]} m(#{ARG[0]} a1) #{EX[0]};\n" +
+ "}\n" +
+ "interface SAM2 {\n" +
+ " #{RET[1]} m(#{ARG[1]} a1) #{EX[1]};\n" +
+ "}\n" +
+ "class Test {\n" +
+ " void m(SAM1 s) { }\n" +
+ " void m(SAM2 s) { }\n" +
+ " { m((#{ARG[0]} x)->{ #{EXPR} }); }\n" +
+ "}\n";
+
+ public static void main(String... args) throws Exception {
+ new ComboTestHelper<StructuralMostSpecificTest>()
+ .withFilter(StructuralMostSpecificTest::hasSameArguments)
+ .withFilter(StructuralMostSpecificTest::hasCompatibleReturns)
+ .withFilter(StructuralMostSpecificTest::hasSameOverloadPhase)
+ .withDimension("EXPR", (x, expr) -> x.lambdaReturnKind = expr, LambdaReturnKind.values())
+ .withArrayDimension("RET", (x, ret, idx) -> x.returnType[idx] = ret, 2, RetTypeKind.values())
+ .withArrayDimension("EX", 2, ExceptionKind.values())
+ .withArrayDimension("ARG", (x, arg, idx) -> x.argumentKind[idx] = arg, 2, ArgTypeKind.values())
+ .run(StructuralMostSpecificTest::new);
}
- void check() {
- checkCount.incrementAndGet();
+ LambdaReturnKind lambdaReturnKind;
+ RetTypeKind[] returnType = new RetTypeKind[2];
+ ArgTypeKind[] argumentKind = new ArgTypeKind[2];
- if (ak1 != ak2)
- return;
+ boolean hasSameArguments() {
+ return argumentKind[0] == argumentKind[1];
+ }
+
+ boolean hasCompatibleReturns() {
+ return lambdaReturnKind.compatibleWith(returnType[0]) &&
+ lambdaReturnKind.compatibleWith(returnType[1]);
+ }
- if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2))
- return;
+ boolean hasSameOverloadPhase() {
+ return lambdaReturnKind.needsConversion(returnType[0]) == lambdaReturnKind.needsConversion(returnType[1]);
+ }
- if (lrk.needsConversion(rt1) != lrk.needsConversion(rt2))
- return;
+ @Override
+ public void doWork() throws Throwable {
+ check(newCompilationTask()
+ .withSourceFromTemplate(sourceTemplate)
+ .withOption("-XDverboseResolution=all,-predef,-internal,-object-init")
+ .analyze());
+ }
- boolean m1MoreSpecific = rt1.moreSpecificThan(rt2);
- boolean m2MoreSpecific = rt2.moreSpecificThan(rt1);
+ void check(Result<Iterable<? extends Element>> result) {
+ boolean m1MoreSpecific = returnType[0].moreSpecificThan(returnType[1]);
+ boolean m2MoreSpecific = returnType[1].moreSpecificThan(returnType[0]);
boolean ambiguous = (m1MoreSpecific == m2MoreSpecific);
- if (ambiguous != diagChecker.ambiguityFound) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nAmbiguity found: " + diagChecker.ambiguityFound +
+ if (ambiguous != ambiguityFound(result)) {
+ fail("invalid diagnostics for combo:\n" +
+ result.compilationInfo() + "\n" +
+ "\nAmbiguity found: " + ambiguityFound(result) +
"\nm1 more specific: " + m1MoreSpecific +
"\nm2 more specific: " + m2MoreSpecific +
"\nexpected ambiguity: " + ambiguous);
@@ -263,44 +231,32 @@
if (!ambiguous) {
String sigToCheck = m1MoreSpecific ? "m(SAM1)" : "m(SAM2)";
- if (!sigToCheck.equals(diagChecker.mostSpecificSig)) {
- throw new Error("invalid most specific method selected:\n" +
- source.getCharContent(true) +
- "\nMost specific found: " + diagChecker.mostSpecificSig +
- "\nm1 more specific: " + m1MoreSpecific +
- "\nm2 more specific: " + m2MoreSpecific);
+ if (!sigToCheck.equals(mostSpecificSignature(result))) {
+ fail("invalid most specific method selected:\n" +
+ result.compilationInfo() + "\n" +
+ "\nMost specific found: " + mostSpecificSignature(result) +
+ "\nm1 more specific: " + m1MoreSpecific +
+ "\nm2 more specific: " + m2MoreSpecific);
}
}
}
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean ambiguityFound;
- String mostSpecificSig;
+ boolean ambiguityFound(Result<Iterable<? extends Element>> result) {
+ return result.containsKey("compiler.err.ref.ambiguous");
+ }
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- try {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
- diagnostic.getCode().equals("compiler.err.ref.ambiguous")) {
- ambiguityFound = true;
- } else if (diagnostic.getKind() == Diagnostic.Kind.NOTE &&
- diagnostic.getCode()
- .equals("compiler.note.verbose.resolve.multi")) {
- ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
- (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic;
- JCDiagnostic.MultilineDiagnostic mdiag =
- (JCDiagnostic.MultilineDiagnostic)dsu.d;
- int mostSpecificIndex = (Integer)mdiag.getArgs()[2];
- mostSpecificSig =
- ((JCDiagnostic)mdiag.getSubdiagnostics()
- .get(mostSpecificIndex)).getArgs()[1].toString();
- }
- } catch (RuntimeException t) {
- t.printStackTrace();
- throw t;
- }
+ String mostSpecificSignature(Result<Iterable<? extends Element>> result) {
+ List<Diagnostic<? extends JavaFileObject>> rsDiag =
+ result.diagnosticsForKey("compiler.note.verbose.resolve.multi");
+ if (rsDiag.nonEmpty()) {
+ ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
+ (ClientCodeWrapper.DiagnosticSourceUnwrapper)rsDiag.head;
+ JCDiagnostic.MultilineDiagnostic mdiag =
+ (JCDiagnostic.MultilineDiagnostic)dsu.d;
+ int mostSpecificIndex = (Integer)mdiag.getArgs()[2];
+ return mdiag.getSubdiagnostics().get(mostSpecificIndex).getArgs()[1].toString();
+ } else {
+ return null;
}
}
-
}
--- a/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,31 +23,31 @@
/**
* @test
- * @bug 8003280 8006694
+ * @bug 8003280 8006694 8129962
* @summary Add lambda tests
* perform automated checks in type inference in lambda expressions
* in different contexts
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../../../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
* @compile TypeInferenceComboTest.java
- * @run main/othervm/timeout=360 TypeInferenceComboTest
+ * @run main TypeInferenceComboTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import com.sun.source.util.JavacTask;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
-public class TypeInferenceComboTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+public class TypeInferenceComboTest extends ComboInstance<TypeInferenceComboTest> {
enum Context {
ASSIGNMENT("SAM#Type s = #LBody;"),
METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" +
@@ -221,82 +221,21 @@
}
}
- boolean checkTypeInference() {
- if (parameterType == TypeKind.VOID) {
- if (lambdaBodyType != LambdaBody.RETURN_VOID)
- return false;
- }
- else if (lambdaBodyType != LambdaBody.RETURN_ARG)
- return false;
-
- return true;
- }
-
- String templateStr = "#C\n" +
- "interface SAM2 {\n" +
- " SAM m();\n" +
- "}\n";
- SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) {
- public String toString() {
- return template.replaceAll("#C",
- samKind.getSam(parameterType, returnType));
- }
- };
-
- SourceFile clientSourceFile = new SourceFile("Client.java",
- "class Client { \n" +
- " #Context\n" +
- "}") {
- public String toString() {
- return template.replaceAll("#Context",
- context.getContext(samKind, samTargetType, keyword,
- parameterType, returnType, lambdaKind, parameterKind,
- genericDeclKind, lambdaBodyType));
- }
- };
-
- public void run() {
- DiagnosticChecker dc = new DiagnosticChecker();
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc,
- null, null, Arrays.asList(samSourceFile, clientSourceFile));
- try {
- ct.analyze();
- } catch (Throwable t) {
- processException(t);
- }
- if (dc.errorFound == checkTypeInference()) {
- throw new AssertionError(samSourceFile + "\n\n" +
- clientSourceFile + "\n" + parameterType + " " + returnType);
- }
- }
-
- abstract class SourceFile extends SimpleJavaFileObject {
-
- protected String template;
-
- public SourceFile(String filename, String template) {
- super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
- this.template = template;
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return toString();
- }
-
- public abstract String toString();
- }
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- boolean errorFound = false;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errorFound = true;
- }
- }
+ public static void main(String[] args) {
+ new ComboTestHelper<TypeInferenceComboTest>()
+ .withFilter(TypeInferenceComboTest::badTestFilter)
+ .withFilter(TypeInferenceComboTest::redundantTestFilter)
+ .withDimension("SAM", (x, sam) -> x.samKind = sam, SamKind.values())
+ .withDimension("SAMTARGET", (x, target) -> x.samTargetType = target, TypeKind.values())
+ .withDimension("PARAMTYPE", (x, param) -> x.parameterType = param, TypeKind.values())
+ .withDimension("RETTYPE", (x, ret) -> x.returnType = ret, TypeKind.values())
+ .withDimension("CTX", (x, ctx) -> x.context = ctx, Context.values())
+ .withDimension("LAMBDABODY", (x, body) -> x.lambdaBodyType = body, LambdaBody.values())
+ .withDimension("LAMBDAKIND", (x, lambda) -> x.lambdaKind = lambda, LambdaKind.values())
+ .withDimension("PARAMKIND", (x, param) -> x.parameterKind = param, ParameterKind.values())
+ .withDimension("KEYWORD", (x, kw) -> x.keyword = kw, Keyword.values())
+ .withDimension("GENDECL", (x, gk) -> x.genericDeclKind = gk, GenericDeclKind.values())
+ .run(TypeInferenceComboTest::new);
}
SamKind samKind;
@@ -310,84 +249,75 @@
Keyword keyword;
GenericDeclKind genericDeclKind;
- TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT,
- TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk,
- ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
- samKind = sk;
- samTargetType = samTargetT;
- parameterType = parameterT;
- returnType = returnT;
- context = c;
- lambdaKind = lk;
- parameterKind = pk;
- keyword = kw;
- lambdaBodyType = lb;
- genericDeclKind = gdk;
+ boolean badTestFilter() {
+ if (samKind == SamKind.NON_GENERIC) {
+ return (parameterType != TypeKind.GENERIC && returnType != TypeKind.GENERIC);
+ } else {
+ return (samTargetType != TypeKind.VOID &&
+ samTargetType != TypeKind.INT &&
+ samTargetType != TypeKind.GENERIC &&
+ (parameterType == TypeKind.GENERIC ||
+ returnType == TypeKind.GENERIC));
+ }
}
- public static void main(String[] args) throws Exception {
- for(Context ct : Context.values()) {
- for (TypeKind returnT : TypeKind.values()) {
- for (TypeKind parameterT : TypeKind.values()) {
- for(LambdaBody lb : LambdaBody.values()) {
- for (ParameterKind parameterK : ParameterKind.values()) {
- for(LambdaKind lambdaK : LambdaKind.values()) {
- for (SamKind sk : SamKind.values()) {
- if (sk == SamKind.NON_GENERIC) {
- generateNonGenericSAM(ct, returnT,
- parameterT, lb, parameterK,
- lambdaK, sk);
- }
- else if (sk == SamKind.GENERIC) {
- generateGenericSAM(ct, returnT,
- parameterT, lb, parameterK,
- lambdaK, sk);
- }
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec(false);
- }
-
- static void generateNonGenericSAM(Context ct, TypeKind returnT,
- TypeKind parameterT, LambdaBody lb, ParameterKind parameterK,
- LambdaKind lambdaK, SamKind sk) {
- if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) {
- pool.execute(new TypeInferenceComboTest(sk, null, parameterT,
- returnT, lb, ct, lambdaK, parameterK, null, null));
+ boolean redundantTestFilter() {
+ if (samKind == SamKind.NON_GENERIC) {
+ return keyword.ordinal() == 0 && samTargetType.ordinal() == 0 && genericDeclKind.ordinal() == 0;
+ } else {
+ return context == Context.METHOD_CALL || genericDeclKind.ordinal() == 0;
}
}
- static void generateGenericSAM(Context ct, TypeKind returnT,
- TypeKind parameterT, LambdaBody lb, ParameterKind parameterK,
- LambdaKind lambdaK, SamKind sk) {
- for (Keyword kw : Keyword.values()) {
- for (TypeKind samTargetT : TypeKind.values()) {
- if(samTargetT != TypeKind.VOID &&
- samTargetT != TypeKind.INT &&
- samTargetT != TypeKind.GENERIC &&
- (parameterT == TypeKind.GENERIC ||
- returnT == TypeKind.GENERIC)) {
- if(ct != Context.METHOD_CALL) {
- pool.execute(
- new TypeInferenceComboTest(sk, samTargetT, parameterT,
- returnT, lb, ct, lambdaK, parameterK, kw, null));
- } else {//Context.METHOD_CALL
- for (GenericDeclKind gdk :
- GenericDeclKind.values())
- pool.execute(
- new TypeInferenceComboTest(sk, samTargetT,
- parameterT, returnT, lb, ct, lambdaK,
- parameterK, kw, gdk));
- }
- }
- }
- }
+ String sam_template = "#{SAM}\n" +
+ "interface SAM2 {\n" +
+ " SAM m();\n" +
+ "}\n";
+
+
+ String client_template = "class Client { \n" +
+ " #{CONTEXT}\n" +
+ "}";
+
+ @Override
+ public void doWork() throws IOException {
+ Result<?> res = newCompilationTask()
+ .withSourceFromTemplate("Sam", sam_template, this::samClass)
+ .withSourceFromTemplate("Client", client_template, this::clientContext)
+ .analyze();
+
+ if (res.hasErrors() == checkTypeInference()) {
+ fail("Unexpected compilation output when compiling instance: " + res.compilationInfo());
+ }
}
+ ComboParameter samClass(String parameterName) {
+ switch (parameterName) {
+ case "SAM":
+ return new ComboParameter.Constant<>(samKind.getSam(parameterType, returnType));
+ default:
+ return null;
+ }
+ }
+
+ ComboParameter clientContext(String parameterName) {
+ switch (parameterName) {
+ case "CONTEXT":
+ return new ComboParameter.Constant<>(context.getContext(samKind, samTargetType,
+ keyword, parameterType, returnType, lambdaKind, parameterKind, genericDeclKind, lambdaBodyType));
+ default:
+ return null;
+ }
+ }
+
+ boolean checkTypeInference() {
+ if (parameterType == TypeKind.VOID) {
+ if (lambdaBodyType != LambdaBody.RETURN_VOID)
+ return false;
+ }
+ else if (lambdaBodyType != LambdaBody.RETURN_ARG)
+ return false;
+
+ return true;
+ }
}
--- a/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.tools.JavaCompiler;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
-
-/**
- * An abstract superclass for threaded tests.
- *
- * This class will try to read a property named test.concurrency.
- * The property can be provided by passing this option to jtreg:
- * -javaoption:-Dtest.concurrency=#
- *
- * If the property is not set the class will use a heuristic to determine the
- * maximum number of threads that can be fired to execute a given test.
- *
- * This code will have to be revisited if jprt starts using concurrency for
- * for running jtreg tests.
- */
-public abstract class JavacTestingAbstractThreadedTest {
-
- protected static AtomicInteger numberOfThreads = new AtomicInteger();
-
- protected static int getThreadPoolSize() {
- Integer testConc = Integer.getInteger("test.concurrency");
- if (testConc != null) return testConc;
- int cores = Runtime.getRuntime().availableProcessors();
- numberOfThreads.set(Math.max(2, Math.min(8, cores / 2)));
- return numberOfThreads.get();
- }
-
- protected static void checkAfterExec() throws InterruptedException {
- checkAfterExec(true);
- };
-
- protected static boolean throwAssertionOnError = true;
-
- protected static boolean printAll = false;
-
- protected static StringWriter errSWriter = new StringWriter();
- protected static PrintWriter errWriter = new PrintWriter(errSWriter);
-
- protected static StringWriter outSWriter = new StringWriter();
- protected static PrintWriter outWriter = new PrintWriter(outSWriter);
-
- protected static void checkAfterExec(boolean printCheckCount)
- throws InterruptedException {
- pool.shutdown();
- pool.awaitTermination(15, TimeUnit.MINUTES);
- if (errCount.get() > 0) {
- if (throwAssertionOnError) {
- closePrinters();
- System.err.println(errSWriter.toString());
- throw new AssertionError(
- String.format("%d errors found", errCount.get()));
- } else {
- System.err.println(
- String.format("%d errors found", errCount.get()));
- }
- } else if (printCheckCount) {
- outWriter.println("Total check executed: " + checkCount.get());
- }
- /*
- * This output is for supporting debugging. It does not mean that a given
- * test had executed that number of threads concurrently. The value printed
- * here is the maximum possible amount.
- */
- closePrinters();
- if (printAll) {
- System.out.println(errSWriter.toString());
- System.out.println(outSWriter.toString());
- }
- System.out.println("Total number of threads in thread pool: " +
- numberOfThreads.get());
- }
-
- protected static void closePrinters() {
- errWriter.close();
- outWriter.close();
- }
-
- protected static void processException(Throwable t) {
- errCount.incrementAndGet();
- t.printStackTrace(errWriter);
- pool.shutdown();
- }
-
- //number of checks executed
- protected static AtomicInteger checkCount = new AtomicInteger();
-
- //number of errors found while running combo tests
- protected static AtomicInteger errCount = new AtomicInteger();
-
- //create default shared JavaCompiler - reused across multiple compilations
- protected static JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-
- protected static ExecutorService pool = Executors.newFixedThreadPool(
- getThreadPoolSize(), new ThreadFactory() {
- @Override
- public Thread newThread(Runnable r) {
- Thread t = new Thread(r);
- t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- pool.shutdown();
- errCount.incrementAndGet();
- e.printStackTrace(System.err);
- }
- });
- return t;
- }
- });
-
- /*
- * File manager is not thread-safe so it cannot be re-used across multiple
- * threads. However we cache per-thread FileManager to avoid excessive
- * object creation
- */
- protected static final ThreadLocal<StandardJavaFileManager> fm =
- new ThreadLocal<StandardJavaFileManager>() {
- @Override protected StandardJavaFileManager initialValue() {
- return comp.getStandardFileManager(null, null, null);
- }
- };
-
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lib/combo/ComboInstance.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 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 combo;
+
+import javax.tools.StandardJavaFileManager;
+import java.util.Optional;
+
+/**
+ * This class is the common superclass of all combo test instances. It defines few helper methods
+ * to build compilation tasks using the shared context object, as well as entry points for
+ * signalling test failures.
+ */
+public abstract class ComboInstance<X extends ComboInstance<X>> {
+
+ /** The test instance result status. */
+ private ResultStatus resultStatus = ResultStatus.PASSED;
+
+ /** The test instance execution environment. */
+ private ComboTestHelper<X>.Env env;
+
+ /**
+ * Entry point for executing a combo test instance; first, the test environment is saved
+ * in the corresponding field, then the instance is run (see {@link ComboInstance#doWork()}.
+ * During execution, the result status will be updated to match the test outcome.
+ */
+ final void run(ComboTestHelper<X>.Env env) {
+ try {
+ this.env = env;
+ doWork();
+ if (resultStatus.isSuccess()) {
+ env.info().passCount++;
+ }
+ } catch (Throwable ex) {
+ resultStatus = ResultStatus.ERROR;
+ env.info().errCount++;
+ env.info().lastError = Optional.of(ex);
+ } finally {
+ this.env = null;
+ }
+ }
+
+ /**
+ * Retrieve a unique ID associated with this test instance.
+ */
+ public int id() {
+ return env.info().comboCount;
+ }
+
+ /**
+ * Retrieve shared file manager.
+ */
+ public StandardJavaFileManager fileManager() {
+ return env.fileManager();
+ }
+
+ /**
+ * Create a new compilation task using shared compilation context.
+ */
+ protected ComboTask newCompilationTask() {
+ return new ComboTask(env);
+ }
+
+ /**
+ * Main test execution entry point; subclasses must implement this method to define the test
+ * logic.
+ */
+ protected abstract void doWork() throws Throwable;
+
+ /**
+ * Report a test failure.
+ */
+ protected void fail() {
+ //dump some default info (such as dimension bindings)
+ fail("Combo instance failed; " + env.bindings);
+ }
+
+ /**
+ * Report a test failure with corresponding failure message.
+ */
+ protected void fail(String msg) {
+ resultStatus = ResultStatus.FAILED;
+ env.info().failCount++;
+ env.info().lastFailure = Optional.of(msg);
+ }
+
+ /**
+ * The status associated with this test instance execution.
+ */
+ enum ResultStatus {
+ /** Test passed. */
+ PASSED(true),
+ /** Test failed. */
+ FAILED(false),
+ /** Test thrown unexpected error/exception. */
+ ERROR(false);
+
+ boolean success;
+
+ ResultStatus(boolean success) {
+ this.success = success;
+ }
+
+ boolean isSuccess() {
+ return success;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lib/combo/ComboParameter.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 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 combo;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A combo parameter represents an 'hole' in a template that can be replaced with a given string.
+ * The schema of such holes is defined in {@link ComboParameter#pattern}; the main routine for
+ * replacing holes in a template scheme is {@link ComboParameter#expandTemplate(String, Resolver)}.
+ */
+public interface ComboParameter {
+
+ /**
+ * A combo parameter can take the form:
+ * <p>
+ * #{MAJOR}
+ * #{MAJOR.}
+ * #{MAJOR.MINOR}
+ * <p>
+ * where MAJOR can be IDENTIFIER or IDENTIFIER[NUMERIC_INDEX]
+ * and MINOR can be an identifier.
+ */
+ Pattern pattern = Pattern.compile("#\\{([A-Z_][A-Z0-9_]*(?:\\[\\d+\\])?)(?:\\.([A-Z0-9_]*))?\\}");
+
+ /**
+ * Entry point for the customizable replacement logic. Subclasses must implement this method to
+ * specify how a given template hole should be expanded. An optional contextual argument is passed
+ * in as parameter, to make expansion more flexible.
+ */
+ String expand(String optParameter);
+
+ /**
+ * Helper class for defining 'constant' combo parameters - i.e. parameters that always expand
+ * as a given string value - regardless of the context.
+ */
+ class Constant<D> implements ComboParameter {
+
+ D data;
+
+ public Constant(D data) {
+ this.data = data;
+ }
+
+ @Override
+ public String expand(String _unused) {
+ return String.valueOf(data);
+ }
+ }
+
+ /**
+ * Helper interface used to lookup parameters given a parameter name.
+ */
+ interface Resolver {
+ ComboParameter lookup(String name);
+ }
+
+ /**
+ * Main routine for replacing holes in a template string. Holes are repeatedly searches, their
+ * corresponding parameters retrieved, and replaced through expansion; since an expansion can
+ * lead to more holes, the process has to be applied until a fixed point is reached.
+ */
+ static String expandTemplate(String template, Resolver resolver) {
+ CharSequence in = template;
+ StringBuffer out = new StringBuffer();
+ while (true) {
+ boolean more = false;
+ Matcher m = pattern.matcher(in);
+ while (m.find()) {
+ String parameterName = m.group(1);
+ String minor = m.group(2);
+ ComboParameter parameter = resolver.lookup(parameterName);
+ if (parameter == null) {
+ throw new IllegalStateException("Unhandled parameter name " + parameterName);
+ }
+
+ String replacement = parameter.expand(minor);
+ more |= pattern.matcher(replacement).find();
+ m.appendReplacement(out, replacement);
+ }
+ m.appendTail(out);
+ if (!more)
+ return out.toString();
+ else {
+ in = out;
+ out = new StringBuffer();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lib/combo/ComboTask.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 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 combo;
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskEvent.Kind;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.util.List;
+import combo.ComboParameter.Resolver;
+
+import javax.lang.model.element.Element;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+/**
+ * This class represents a compilation task associated with a combo test instance. This is a small
+ * wrapper around {@link JavacTask} which allows for fluent setup style and which makes use of
+ * the shared compilation context to speedup performances.
+ */
+public class ComboTask {
+
+ /** Sources to be compiled in this task. */
+ private List<JavaFileObject> sources = List.nil();
+
+ /** Options associated with this task. */
+ private List<String> options = List.nil();
+
+ /** Diagnostic collector. */
+ private DiagnosticCollector diagsCollector = new DiagnosticCollector();
+
+ /** Output writer. */
+ private Writer out;
+
+ /** Listeners associated with this task. */
+ private List<TaskListener> listeners = List.nil();
+
+ /** Underlying javac task object. */
+ private JavacTask task;
+
+ /** Combo execution environment. */
+ private ComboTestHelper<?>.Env env;
+
+ ComboTask(ComboTestHelper<?>.Env env) {
+ this.env = env;
+ }
+
+ /**
+ * Add a new source to this task.
+ */
+ public ComboTask withSource(JavaFileObject comboSource) {
+ sources = sources.prepend(comboSource);
+ return this;
+ }
+
+ /**
+ * Add a new template source with given name to this task; the template is replaced with
+ * corresponding combo parameters (as defined in the combo test environment).
+ */
+ public ComboTask withSourceFromTemplate(String name, String template) {
+ return withSource(new ComboTemplateSource(name, template));
+ }
+
+ /**
+ * Add a new template source with default name ("Test") to this task; the template is replaced with
+ * corresponding combo parameters (as defined in the combo test environment).
+ */
+ public ComboTask withSourceFromTemplate(String template) {
+ return withSource(new ComboTemplateSource("Test", template));
+ }
+
+ /**
+ * Add a new template source with given name to this task; the template is replaced with
+ * corresponding combo parameters (as defined in the combo test environment). A custom resolver
+ * is used to add combo parameter mappings to the current combo test environment.
+ */
+ public ComboTask withSourceFromTemplate(String name, String template, Resolver resolver) {
+ return withSource(new ComboTemplateSource(name, template, resolver));
+ }
+
+ /**
+ * Add a new template source with default name ("Test") to this task; the template is replaced with
+ * corresponding combo parameters (as defined in the combo test environment). A custom resolver
+ * is used to add combo parameter mappings to the current combo test environment.
+ */
+ public ComboTask withSourceFromTemplate(String template, Resolver resolver) {
+ return withSource(new ComboTemplateSource("Test", template, resolver));
+ }
+
+ /**
+ * Add a new option to this task.
+ */
+ public ComboTask withOption(String opt) {
+ options = options.append(opt);
+ return this;
+ }
+
+ /**
+ * Add a set of options to this task.
+ */
+ public ComboTask withOptions(String[] opts) {
+ for (String opt : opts) {
+ options = options.append(opt);
+ }
+ return this;
+ }
+
+ /**
+ * Add a set of options to this task.
+ */
+ public ComboTask withOptions(Iterable<? extends String> opts) {
+ for (String opt : opts) {
+ options = options.append(opt);
+ }
+ return this;
+ }
+
+ /**
+ * Set the output writer associated with this task.
+ */
+ public ComboTask withWriter(Writer out) {
+ this.out = out;
+ return this;
+ }
+
+ /**
+ * Add a task listener to this task.
+ */
+ public ComboTask withListener(TaskListener listener) {
+ listeners = listeners.prepend(listener);
+ return this;
+ }
+
+ /**
+ * Parse the sources associated with this task.
+ */
+ public Result<Iterable<? extends CompilationUnitTree>> parse() throws IOException {
+ return new Result<>(getTask().parse());
+ }
+
+ /**
+ * Parse and analyzes the sources associated with this task.
+ */
+ public Result<Iterable<? extends Element>> analyze() throws IOException {
+ return new Result<>(getTask().analyze());
+ }
+
+ /**
+ * Parse, analyze and perform code generation for the sources associated with this task.
+ */
+ public Result<Iterable<? extends JavaFileObject>> generate() throws IOException {
+ return new Result<>(getTask().generate());
+ }
+
+ /**
+ * Fork a new compilation task; if possible the compilation context from previous executions is
+ * retained (see comments in ReusableContext as to when it's safe to do so); otherwise a brand
+ * new context is created.
+ */
+ public JavacTask getTask() {
+ if (task == null) {
+ ReusableContext context = env.context();
+ String opts = options == null ? "" :
+ StreamSupport.stream(options.spliterator(), false).collect(Collectors.joining());
+ context.clear();
+ if (!context.polluted && (context.opts == null || context.opts.equals(opts))) {
+ //we can reuse former context
+ env.info().ctxReusedCount++;
+ } else {
+ env.info().ctxDroppedCount++;
+ //it's not safe to reuse context - create a new one
+ context = env.setContext(new ReusableContext());
+ }
+ context.opts = opts;
+ JavacTask javacTask = ((JavacTool)env.javaCompiler()).getTask(out, env.fileManager(),
+ diagsCollector, options, null, sources, context);
+ javacTask.setTaskListener(context);
+ for (TaskListener l : listeners) {
+ javacTask.addTaskListener(l);
+ }
+ task = javacTask;
+ }
+ return task;
+ }
+
+ /**
+ * This class is used to help clients accessing the results of a given compilation task.
+ * Contains several helper methods to inspect diagnostics generated during the task execution.
+ */
+ public class Result<D> {
+
+ /** The underlying compilation results. */
+ private final D data;
+
+ public Result(D data) {
+ this.data = data;
+ }
+
+ public D get() {
+ return data;
+ }
+
+ /**
+ * Did this task generate any error diagnostics?
+ */
+ public boolean hasErrors() {
+ return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.ERROR);
+ }
+
+ /**
+ * Did this task generate any warning diagnostics?
+ */
+ public boolean hasWarnings() {
+ return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.WARNING);
+ }
+
+ /**
+ * Did this task generate any note diagnostics?
+ */
+ public boolean hasNotes() {
+ return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.NOTE);
+ }
+
+ /**
+ * Did this task generate any diagnostic with given key?
+ */
+ public boolean containsKey(String key) {
+ return diagsCollector.diagsByKeys.containsKey(key);
+ }
+
+ /**
+ * Retrieve the list of diagnostics of a given kind.
+ */
+ public List<Diagnostic<? extends JavaFileObject>> diagnosticsForKind(Diagnostic.Kind kind) {
+ List<Diagnostic<? extends JavaFileObject>> diags = diagsCollector.diagsByKind.get(kind);
+ return diags != null ? diags : List.nil();
+ }
+
+ /**
+ * Retrieve the list of diagnostics with given key.
+ */
+ public List<Diagnostic<? extends JavaFileObject>> diagnosticsForKey(String key) {
+ List<Diagnostic<? extends JavaFileObject>> diags = diagsCollector.diagsByKeys.get(key);
+ return diags != null ? diags : List.nil();
+ }
+
+ /**
+ * Dump useful info associated with this task.
+ */
+ public String compilationInfo() {
+ return "instance#" + env.info().comboCount + ":[ options = " + options
+ + ", diagnostics = " + diagsCollector.diagsByKeys.keySet()
+ + ", dimensions = " + env.bindings
+ + ", sources = \n" + sources.stream().map(s -> {
+ try {
+ return s.getCharContent(true);
+ } catch (IOException ex) {
+ return "";
+ }
+ }).collect(Collectors.joining(",")) + "]";
+ }
+ }
+
+ /**
+ * This class represents a Java source file whose contents are defined in terms of a template
+ * string. The holes in such template are expanded using corresponding combo parameter
+ * instances which can be retrieved using a resolver object.
+ */
+ class ComboTemplateSource extends SimpleJavaFileObject {
+
+ String source;
+ Map<String, ComboParameter> localParametersCache = new HashMap<>();
+
+ protected ComboTemplateSource(String name, String template) {
+ this(name, template, null);
+ }
+
+ protected ComboTemplateSource(String name, String template, Resolver resolver) {
+ super(URI.create("myfo:/" + env.info().comboCount + "/" + name + ".java"), Kind.SOURCE);
+ source = ComboParameter.expandTemplate(template, pname -> resolveParameter(pname, resolver));
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+
+ /**
+ * Combo parameter resolver function. First parameters are looked up in the global environment,
+ * then the local environment is looked up as a fallback.
+ */
+ ComboParameter resolveParameter(String pname, Resolver resolver) {
+ //first search the env
+ ComboParameter parameter = env.parametersCache.get(pname);
+ if (parameter == null) {
+ //then lookup local cache
+ parameter = localParametersCache.get(pname);
+ if (parameter == null && resolver != null) {
+ //if still null and we have a custom resolution function, try that
+ parameter = resolver.lookup(pname);
+ if (parameter != null) {
+ //if a match was found, store it in the local cache to aviod redundant recomputation
+ localParametersCache.put(pname, parameter);
+ }
+ }
+ }
+ return parameter;
+ }
+ }
+
+ /**
+ * Helper class to collect all diagnostic generated during the execution of a given compilation task.
+ */
+ class DiagnosticCollector implements DiagnosticListener<JavaFileObject> {
+
+ Map<Diagnostic.Kind, List<Diagnostic<? extends JavaFileObject>>> diagsByKind = new HashMap<>();
+ Map<String, List<Diagnostic<? extends JavaFileObject>>> diagsByKeys = new HashMap<>();
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ List<Diagnostic<? extends JavaFileObject>> diags =
+ diagsByKeys.getOrDefault(diagnostic.getCode(), List.nil());
+ diagsByKeys.put(diagnostic.getCode(), diags.prepend(diagnostic));
+ Diagnostic.Kind kind = diagnostic.getKind();
+ diags = diagsByKind.getOrDefault(kind, List.nil());
+ diagsByKind.put(kind, diags.prepend(diagnostic));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lib/combo/ComboTestHelper.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 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 combo;
+
+import javax.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Stack;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+
+/**
+ * An helper class for defining combinatorial (aka "combo" tests). A combo test is made up of one
+ * or more 'dimensions' - each of which represent a different axis of the test space. For instance,
+ * if we wanted to test class/interface declaration, one dimension could be the keyword used for
+ * the declaration (i.e. 'class' vs. 'interface') while another dimension could be the class/interface
+ * modifiers (i.e. 'public', 'pachake-private' etc.). A combo test consists in running a test instance
+ * for each point in the test space; that is, for any combination of the combo test dimension:
+ * <p>
+ * 'public' 'class'
+ * 'public' interface'
+ * 'package-private' 'class'
+ * 'package-private' 'interface'
+ * ...
+ * <p>
+ * A new test instance {@link ComboInstance} is created, and executed, after its dimensions have been
+ * initialized accordingly. Each instance can either pass, fail or throw an unexpected error; this helper
+ * class defines several policies for how failures should be handled during a combo test execution
+ * (i.e. should errors be ignored? Do we want the first failure to result in a failure of the whole
+ * combo test?).
+ * <p>
+ * Additionally, this helper class allows to specify filter methods that can be used to throw out
+ * illegal combinations of dimensions - for instance, in the example above, we might want to exclude
+ * all combinations involving 'protected' and 'private' modifiers, which are disallowed for toplevel
+ * declarations.
+ * <p>
+ * While combo tests can be used for a variety of workloads, typically their main task will consist
+ * in performing some kind of javac compilation. For this purpose, this framework defines an optimized
+ * javac context {@link ReusableContext} which can be shared across multiple combo instances,
+ * when the framework detects it's safe to do so. This allows to reduce the overhead associated with
+ * compiler initialization when the test space is big.
+ */
+public class ComboTestHelper<X extends ComboInstance<X>> {
+
+ /** Failure mode. */
+ FailMode failMode = FailMode.FAIL_FAST;
+
+ /** Ignore mode. */
+ IgnoreMode ignoreMode = IgnoreMode.IGNORE_NONE;
+
+ /** Combo test instance filter. */
+ Optional<Predicate<X>> optFilter = Optional.empty();
+
+ /** Combo test dimensions. */
+ List<DimensionInfo<?>> dimensionInfos = new ArrayList<>();
+
+ /** Combo test stats. */
+ Info info = new Info();
+
+ /** Shared JavaCompiler used across all combo test instances. */
+ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+
+ /** Shared file manager used across all combo test instances. */
+ StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+
+ /** Shared context used across all combo instances. */
+ ReusableContext context = new ReusableContext();
+
+ /**
+ * Set failure mode for this combo test.
+ */
+ public ComboTestHelper<X> withFailMode(FailMode failMode) {
+ this.failMode = failMode;
+ return this;
+ }
+
+ /**
+ * Set ignore mode for this combo test.
+ */
+ public ComboTestHelper<X> withIgnoreMode(IgnoreMode ignoreMode) {
+ this.ignoreMode = ignoreMode;
+ return this;
+ }
+
+ /**
+ * Set a filter for combo test instances to be ignored.
+ */
+ public ComboTestHelper<X> withFilter(Predicate<X> filter) {
+ optFilter = Optional.of(optFilter.map(filter::and).orElse(filter));
+ return this;
+ }
+
+ /**
+ * Adds a new dimension to this combo test, with a given name an array of values.
+ */
+ @SafeVarargs
+ public final <D> ComboTestHelper<X> withDimension(String name, D... dims) {
+ return withDimension(name, null, dims);
+ }
+
+ /**
+ * Adds a new dimension to this combo test, with a given name, an array of values and a
+ * coresponding setter to be called in order to set the dimension value on the combo test instance
+ * (before test execution).
+ */
+ @SuppressWarnings("unchecked")
+ @SafeVarargs
+ public final <D> ComboTestHelper<X> withDimension(String name, DimensionSetter<X, D> setter, D... dims) {
+ dimensionInfos.add(new DimensionInfo<>(name, dims, setter));
+ return this;
+ }
+
+ /**
+ * Adds a new array dimension to this combo test, with a given base name. This allows to specify
+ * multiple dimensions at once; the names of the underlying dimensions will be generated from the
+ * base name, using standard array bracket notation - i.e. "DIM[0]", "DIM[1]", etc.
+ */
+ @SafeVarargs
+ public final <D> ComboTestHelper<X> withArrayDimension(String name, int size, D... dims) {
+ return withArrayDimension(name, null, size, dims);
+ }
+
+ /**
+ * Adds a new array dimension to this combo test, with a given base name, an array of values and a
+ * coresponding array setter to be called in order to set the dimension value on the combo test
+ * instance (before test execution). This allows to specify multiple dimensions at once; the names
+ * of the underlying dimensions will be generated from the base name, using standard array bracket
+ * notation - i.e. "DIM[0]", "DIM[1]", etc.
+ */
+ @SafeVarargs
+ public final <D> ComboTestHelper<X> withArrayDimension(String name, ArrayDimensionSetter<X, D> setter, int size, D... dims) {
+ for (int i = 0 ; i < size ; i++) {
+ dimensionInfos.add(new ArrayDimensionInfo<>(name, dims, i, setter));
+ }
+ return this;
+ }
+
+ /**
+ * Returns the stat object associated with this combo test.
+ */
+ public Info info() {
+ return info;
+ }
+
+ /**
+ * Runs this combo test. This will generate the combinatorial explosion of all dimensions, and
+ * execute a new test instance (built using given supplier) for each such combination.
+ */
+ public void run(Supplier<X> instanceBuilder) {
+ run(instanceBuilder, null);
+ }
+
+ /**
+ * Runs this combo test. This will generate the combinatorial explosion of all dimensions, and
+ * execute a new test instance (built using given supplier) for each such combination. Before
+ * executing the test instance entry point, the supplied initialization method is called on
+ * the test instance; this is useful for ad-hoc test instance initialization once all the dimension
+ * values have been set.
+ */
+ public void run(Supplier<X> instanceBuilder, Consumer<X> initAction) {
+ runInternal(0, new Stack<>(), instanceBuilder, Optional.ofNullable(initAction));
+ end();
+ }
+
+ /**
+ * Generate combinatorial explosion of all dimension values and create a new test instance
+ * for each combination.
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ private void runInternal(int index, Stack<DimensionBinding<?>> bindings, Supplier<X> instanceBuilder, Optional<Consumer<X>> initAction) {
+ if (index == dimensionInfos.size()) {
+ runCombo(instanceBuilder, initAction, bindings);
+ } else {
+ DimensionInfo<?> dinfo = dimensionInfos.get(index);
+ for (Object d : dinfo.dims) {
+ bindings.push(new DimensionBinding(d, dinfo));
+ runInternal(index + 1, bindings, instanceBuilder, initAction);
+ bindings.pop();
+ }
+ }
+ }
+
+ /**
+ * Run a new test instance using supplied dimension bindings. All required setters and initialization
+ * method are executed before calling the instance main entry point. Also checks if the instance
+ * is compatible with the specified test filters; if not, the test is simply skipped.
+ */
+ @SuppressWarnings("unchecked")
+ private void runCombo(Supplier<X> instanceBuilder, Optional<Consumer<X>> initAction, List<DimensionBinding<?>> bindings) {
+ X x = instanceBuilder.get();
+ for (DimensionBinding<?> binding : bindings) {
+ binding.init(x);
+ }
+ initAction.ifPresent(action -> action.accept(x));
+ info.comboCount++;
+ if (!optFilter.isPresent() || optFilter.get().test(x)) {
+ x.run(new Env(bindings));
+ if (failMode.shouldStop(ignoreMode, info)) {
+ end();
+ }
+ } else {
+ info.skippedCount++;
+ }
+ }
+
+ /**
+ * This method is executed upon combo test completion (either normal or erroneous). Closes down
+ * all pending resources and dumps useful stats info.
+ */
+ private void end() {
+ try {
+ fm.close();
+ if (info.hasFailures()) {
+ throw new AssertionError("Failure when executing combo:" + info.lastFailure.orElse(""));
+ } else if (info.hasErrors()) {
+ throw new AssertionError("Unexpected exception while executing combo", info.lastError.get());
+ }
+ } catch (IOException ex) {
+ throw new AssertionError("Failure when closing down shared file manager; ", ex);
+ } finally {
+ info.dump();
+ }
+ }
+
+ /**
+ * Functional interface for specifying combo test instance setters.
+ */
+ public interface DimensionSetter<X extends ComboInstance<X>, D> {
+ void set(X x, D d);
+ }
+
+ /**
+ * Functional interface for specifying combo test instance array setters. The setter method
+ * receives an extra argument for the index of the array element to be set.
+ */
+ public interface ArrayDimensionSetter<X extends ComboInstance<X>, D> {
+ void set(X x, D d, int index);
+ }
+
+ /**
+ * Dimension descriptor; each dimension has a name, an array of value and an optional setter
+ * to be called on the associated combo test instance.
+ */
+ class DimensionInfo<D> {
+ String name;
+ D[] dims;
+ boolean isParameter;
+ Optional<DimensionSetter<X, D>> optSetter;
+
+ DimensionInfo(String name, D[] dims, DimensionSetter<X, D> setter) {
+ this.name = name;
+ this.dims = dims;
+ this.optSetter = Optional.ofNullable(setter);
+ this.isParameter = dims[0] instanceof ComboParameter;
+ }
+ }
+
+ /**
+ * Array dimension descriptor. The dimension name is derived from a base name and an index using
+ * standard bracket notation; ; the setter accepts an additional 'index' argument to point
+ * to the array element to be initialized.
+ */
+ class ArrayDimensionInfo<D> extends DimensionInfo<D> {
+ public ArrayDimensionInfo(String name, D[] dims, int index, ArrayDimensionSetter<X, D> setter) {
+ super(String.format("%s[%d]", name, index), dims,
+ setter != null ? (x, d) -> setter.set(x, d, index) : null);
+ }
+ }
+
+ /**
+ * Failure policies for a combo test run.
+ */
+ public enum FailMode {
+ /** Combo test fails when first failure is detected. */
+ FAIL_FAST,
+ /** Combo test fails after all instances have been executed. */
+ FAIL_AFTER;
+
+ boolean shouldStop(IgnoreMode ignoreMode, Info info) {
+ switch (this) {
+ case FAIL_FAST:
+ return !ignoreMode.canIgnore(info);
+ default:
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Ignore policies for a combo test run.
+ */
+ public enum IgnoreMode {
+ /** No error or failure is ignored. */
+ IGNORE_NONE,
+ /** Only errors are ignored. */
+ IGNORE_ERRORS,
+ /** Only failures are ignored. */
+ IGNORE_FAILURES,
+ /** Both errors and failures are ignored. */
+ IGNORE_ALL;
+
+ boolean canIgnore(Info info) {
+ switch (this) {
+ case IGNORE_ERRORS:
+ return info.failCount == 0;
+ case IGNORE_FAILURES:
+ return info.errCount == 0;
+ case IGNORE_ALL:
+ return true;
+ default:
+ return info.failCount == 0 && info.errCount == 0;
+ }
+ }
+ }
+
+ /**
+ * A dimension binding. This is essentially a pair of a dimension value and its corresponding
+ * dimension info.
+ */
+ class DimensionBinding<D> {
+ D d;
+ DimensionInfo<D> info;
+
+ DimensionBinding(D d, DimensionInfo<D> info) {
+ this.d = d;
+ this.info = info;
+ }
+
+ void init(X x) {
+ info.optSetter.ifPresent(setter -> setter.set(x, d));
+ }
+
+ public String toString() {
+ return String.format("(%s -> %s)", info.name, d);
+ }
+ }
+
+ /**
+ * This class is used to keep track of combo tests stats; info such as numbero of failures/errors,
+ * number of times a context has been shared/dropped are all recorder here.
+ */
+ public static class Info {
+ int failCount;
+ int errCount;
+ int passCount;
+ int comboCount;
+ int skippedCount;
+ int ctxReusedCount;
+ int ctxDroppedCount;
+ Optional<String> lastFailure = Optional.empty();
+ Optional<Throwable> lastError = Optional.empty();
+
+ void dump() {
+ System.err.println(String.format("%d total checks executed", comboCount));
+ System.err.println(String.format("%d successes found", passCount));
+ System.err.println(String.format("%d failures found", failCount));
+ System.err.println(String.format("%d errors found", errCount));
+ System.err.println(String.format("%d skips found", skippedCount));
+ System.err.println(String.format("%d contexts shared", ctxReusedCount));
+ System.err.println(String.format("%d contexts dropped", ctxDroppedCount));
+ }
+
+ public boolean hasFailures() {
+ return failCount != 0;
+ }
+
+ public boolean hasErrors() {
+ return errCount != 0;
+ }
+ }
+
+ /**
+ * THe execution environment for a given combo test instance. An environment contains the
+ * bindings for all the dimensions, along with the combo parameter cache (this is non-empty
+ * only if one or more dimensions are subclasses of the {@code ComboParameter} interface).
+ */
+ class Env {
+ List<DimensionBinding<?>> bindings;
+ Map<String, ComboParameter> parametersCache = new HashMap<>();
+
+ @SuppressWarnings({"Unchecked", "rawtypes"})
+ Env(List<DimensionBinding<?>> bindings) {
+ this.bindings = bindings;
+ for (DimensionBinding<?> binding : bindings) {
+ if (binding.info.isParameter) {
+ parametersCache.put(binding.info.name, (ComboParameter)binding.d);
+ };
+ }
+ }
+
+ Info info() {
+ return ComboTestHelper.this.info();
+ }
+
+ StandardJavaFileManager fileManager() {
+ return fm;
+ }
+
+ JavaCompiler javaCompiler() {
+ return comp;
+ }
+
+ ReusableContext context() {
+ return context;
+ }
+
+ ReusableContext setContext(ReusableContext context) {
+ return ComboTestHelper.this.context = context;
+ }
+ }
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lib/combo/ReusableContext.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 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 combo;
+
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskEvent.Kind;
+import com.sun.source.util.TaskListener;
+import com.sun.source.util.TreeScanner;
+import com.sun.tools.javac.api.MultiTaskListener;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.comp.Check;
+import com.sun.tools.javac.comp.CompileStates;
+import com.sun.tools.javac.comp.Enter;
+import com.sun.tools.javac.main.Arguments;
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A reusable context is a context that can be used safely across multiple compilation rounds
+ * arising from execution of a combo test. It achieves reuse by replacing some components
+ * (most notably JavaCompiler and Log) with reusable counterparts, and by exposing a method
+ * to cleanup leftovers from previous compilation.
+ * <p>
+ * There are, however, situations in which reusing the context is not safe: (i) when different
+ * compilations are using different sets of compiler options (as most option values are cached
+ * inside components themselves) and (ii) when the compilation unit happens to redefine classes
+ * in the java.* packages.
+ */
+class ReusableContext extends Context implements TaskListener {
+
+ Set<CompilationUnitTree> roots = new HashSet<>();
+
+ String opts;
+ boolean polluted = false;
+
+ ReusableContext() {
+ super();
+ put(Log.logKey, ReusableLog.factory);
+ put(JavaCompiler.compilerKey, ReusableJavaCompiler.factory);
+ }
+
+ void clear() {
+ drop(Arguments.argsKey);
+ drop(DiagnosticListener.class);
+ drop(Log.outKey);
+ drop(JavaFileManager.class);
+ drop(JavacTask.class);
+
+ if (ht.get(Log.logKey) instanceof ReusableLog) {
+ //log already inited - not first round
+ ((ReusableLog)Log.instance(this)).clear();
+ Enter.instance(this).newRound();
+ ((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear();
+ Types.instance(this).newRound();
+ Check.instance(this).newRound();
+ CompileStates.instance(this).clear();
+ MultiTaskListener.instance(this).clear();
+
+ //find if any of the roots have redefined java.* classes
+ Symtab syms = Symtab.instance(this);
+ new TreeScanner<Void, Void>() {
+ @Override
+ public Void visitClass(ClassTree node, Void aVoid) {
+ Symbol sym = ((JCClassDecl)node).sym;
+ if (sym != null) {
+ syms.classes.remove(sym.flatName());
+ if (sym.flatName().toString().startsWith("java.")) {
+ polluted = true;
+ }
+ }
+ return super.visitClass(node, aVoid);
+ }
+ }.scan(roots, null);
+ roots.clear();
+ }
+ }
+
+ @Override
+ public void finished(TaskEvent e) {
+ if (e.getKind() == Kind.PARSE) {
+ roots.add(e.getCompilationUnit());
+ }
+ }
+
+ @Override
+ public void started(TaskEvent e) {
+ //do nothing
+ }
+
+ <T> void drop(Key<T> k) {
+ ht.remove(k);
+ }
+
+ <T> void drop(Class<T> c) {
+ ht.remove(key(c));
+ }
+
+ /**
+ * Reusable JavaCompiler; exposes a method to clean up the component from leftovers associated with
+ * previous compilations.
+ */
+ static class ReusableJavaCompiler extends JavaCompiler {
+
+ static Factory<JavaCompiler> factory = ReusableJavaCompiler::new;
+
+ ReusableJavaCompiler(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void close() {
+ //do nothing
+ }
+
+ void clear() {
+ newRound();
+ }
+
+ @Override
+ protected void checkReusable() {
+ //do nothing - it's ok to reuse the compiler
+ }
+ }
+
+ /**
+ * Reusable Log; exposes a method to clean up the component from leftovers associated with
+ * previous compilations.
+ */
+ static class ReusableLog extends Log {
+
+ static Factory<Log> factory = ReusableLog::new;
+
+ Context context;
+
+ ReusableLog(Context context) {
+ super(context);
+ this.context = context;
+ }
+
+ void clear() {
+ recorded.clear();
+ sourceMap.clear();
+ nerrors = 0;
+ nwarnings = 0;
+ //Set a fake listener that will lazily lookup the context for the 'real' listener. Since
+ //this field is never updated when a new task is created, we cannot simply reset the field
+ //or keep old value. This is a hack to workaround the limitations in the current infrastructure.
+ diagListener = new DiagnosticListener<JavaFileObject>() {
+ DiagnosticListener<JavaFileObject> cachedListener;
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ if (cachedListener == null) {
+ cachedListener = context.get(DiagnosticListener.class);
+ }
+ cachedListener.report(diagnostic);
+ }
+ };
+ }
+ }
+}
--- a/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,30 +23,31 @@
/*
* @test
- * @bug 7030606 8006694
+ * @bug 7030606 8006694 8129962
* @summary Project-coin: multi-catch types should be pairwise disjoint
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm DisjunctiveTypeWellFormednessTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main DisjunctiveTypeWellFormednessTest
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import com.sun.source.util.JavacTask;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
-public class DisjunctiveTypeWellFormednessTest
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
- enum Alternative {
+public class DisjunctiveTypeWellFormednessTest extends ComboInstance<DisjunctiveTypeWellFormednessTest> {
+
+ enum Alternative implements ComboParameter {
EXCEPTION("Exception"),
RUNTIME_EXCEPTION("RuntimeException"),
IO_EXCEPTION("java.io.IOException"),
@@ -55,21 +56,10 @@
String exceptionStr;
- private Alternative(String exceptionStr) {
+ Alternative(String exceptionStr) {
this.exceptionStr = exceptionStr;
}
- static String makeDisjunctiveType(Alternative... alternatives) {
- StringBuilder buf = new StringBuilder();
- String sep = "";
- for (Alternative alternative : alternatives) {
- buf.append(sep);
- buf.append(alternative.exceptionStr);
- sep = "|";
- }
- return buf.toString();
- }
-
boolean disjoint(Alternative that) {
return disjoint[this.ordinal()][that.ordinal()];
}
@@ -82,135 +72,85 @@
/*FileNotFoundException*/ { false, true, false, false, true },
/*IllegalArgumentException*/ { false, false, true, true, false }
};
+
+ @Override
+ public String expand(String optParameter) {
+ return exceptionStr;
+ }
}
- enum Arity {
- ONE(1),
- TWO(2),
- THREE(3),
- FOUR(4),
- FIVE(5);
+ enum Arity implements ComboParameter {
+ ONE(1, "#{TYPE[0]}"),
+ TWO(2, "#{TYPE[0]} | #{TYPE[1]}"),
+ THREE(3, "#{TYPE[0]} | #{TYPE[1]} | #{TYPE[2]}"),
+ FOUR(4, "#{TYPE[0]} | #{TYPE[1]} | #{TYPE[2]} | #{TYPE[3]}"),
+ FIVE(5, "#{TYPE[0]} | #{TYPE[1]} | #{TYPE[2]} | #{TYPE[3]} | #{TYPE[4]}");
int n;
+ String arityTemplate;
- private Arity(int n) {
+ Arity(int n, String arityTemplate) {
this.n = n;
+ this.arityTemplate = arityTemplate;
+ }
+
+ @Override
+ public String expand(String optParameter) {
+ return arityTemplate;
}
}
public static void main(String... args) throws Exception {
- for (Arity arity : Arity.values()) {
- for (Alternative a1 : Alternative.values()) {
- if (arity == Arity.ONE) {
- pool.execute(new DisjunctiveTypeWellFormednessTest(a1));
- continue;
- }
- for (Alternative a2 : Alternative.values()) {
- if (arity == Arity.TWO) {
- pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2));
- continue;
- }
- for (Alternative a3 : Alternative.values()) {
- if (arity == Arity.THREE) {
- pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3));
- continue;
- }
- for (Alternative a4 : Alternative.values()) {
- if (arity == Arity.FOUR) {
- pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4));
- continue;
- }
- for (Alternative a5 : Alternative.values()) {
- pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4, a5));
- }
- }
- }
+ new ComboTestHelper<DisjunctiveTypeWellFormednessTest>()
+ .withFilter(DisjunctiveTypeWellFormednessTest::arityFilter)
+ .withDimension("CTYPE", (x, arity) -> x.arity = arity, Arity.values())
+ .withArrayDimension("TYPE", (x, type, idx) -> x.alternatives[idx] = type, 5, Alternative.values())
+ .run(DisjunctiveTypeWellFormednessTest::new);
+ }
+
+ Arity arity;
+ Alternative[] alternatives = new Alternative[5];
+
+ boolean arityFilter() {
+ for (int i = arity.n; i < alternatives.length ; i++) {
+ if (alternatives[i].ordinal() != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ String template = "class Test {\n" +
+ "void test() {\n" +
+ "try {} catch (#{CTYPE} e) {}\n" +
+ "}\n" +
+ "}\n";
+
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withSourceFromTemplate(template)
+ .analyze());
+ }
+
+ void check(Result<?> res) {
+
+ int non_disjoint = 0;
+ for (int i = 0 ; i < arity.n ; i++) {
+ for (int j = 0 ; j < i ; j++) {
+ if (!alternatives[i].disjoint(alternatives[j])) {
+ non_disjoint++;
+ break;
}
}
}
- checkAfterExec(false);
- }
-
- Alternative[] alternatives;
- JavaSource source;
- DiagnosticChecker diagChecker;
-
- DisjunctiveTypeWellFormednessTest(Alternative... alternatives) {
- this.alternatives = alternatives;
- this.source = new JavaSource();
- this.diagChecker = new DiagnosticChecker();
- }
-
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "class Test {\n" +
- "void test() {\n" +
- "try {} catch (#T e) {}\n" +
- "}\n" +
- "}\n";
-
- String source;
-
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replace("#T", Alternative.makeDisjunctiveType(alternatives));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
+ int foundErrs = res.diagnosticsForKey("compiler.err.multicatch.types.must.be.disjoint").size();
+ if (non_disjoint != foundErrs) {
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
+ "\nFound errors: " + foundErrs +
+ "\nExpected errors: " + non_disjoint);
}
}
-
- @Override
- public void run() {
- JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
- null, null, Arrays.asList(source));
- try {
- ct.analyze();
- } catch (Throwable t) {
- processException(t);
- return;
- }
- check();
- }
-
- void check() {
-
- int non_disjoint = 0;
- int i = 0;
- for (Alternative a1 : alternatives) {
- int j = 0;
- for (Alternative a2 : alternatives) {
- if (i == j) continue;
- if (!a1.disjoint(a2)) {
- non_disjoint++;
- break;
- }
- j++;
- }
- i++;
- }
-
- if (non_disjoint != diagChecker.errorsFound) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nFound errors: " + diagChecker.errorsFound +
- "\nExpected errors: " + non_disjoint);
- }
- }
-
- static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- int errorsFound;
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
- diagnostic.getCode().startsWith("compiler.err.multicatch.types.must.be.disjoint")) {
- errorsFound++;
- }
- }
- }
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/parser/8134007/T8134007.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,488 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8134007
+ * @summary Improve string folding
+ * @compile T8134007.java
+ */
+class T8134007 {
+ String v = "";
+
+ //interleaved non-literals
+ String s1 = "Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v;
+
+ //heading non-literal
+ String s2 = v + "Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9";
+
+ //trailing non-literal
+ String s3 = "Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9"
+ +"Str0" + "Str1" + "Str2" + "Str3" + "Str4" + "Str5" + "Str6" + "Str7" + "Str8" + "Str9" + v;
+}
--- a/langtools/test/tools/javac/resolve/BitWiseOperators.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/resolve/BitWiseOperators.java Mon Sep 14 07:03:04 2015 +0000
@@ -21,47 +21,30 @@
* questions.
*/
-/**@test
- * @bug 8082311
+/*
+ * @test
+ * @bug 8082311 8129962
* @summary Verify that bitwise operators don't allow to mix numeric and boolean operands.
* @library ../lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main BitWiseOperators
*/
import com.sun.tools.javac.util.StringUtils;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.List;
-import javax.tools.DiagnosticCollector;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-public class BitWiseOperators extends JavacTestingAbstractThreadedTest {
- public static void main(String... args) {
- new BitWiseOperators().run();
- }
+import java.io.IOException;
- void run() {
- for (TYPE type1 : TYPE.values()) {
- for (OPERATION op : OPERATION.values()) {
- for (TYPE type2 : TYPE.values()) {
- runTest(type1, op, type2);
- }
- }
- }
- }
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
- void runTest(TYPE type1, OPERATION op, TYPE type2) {
- DiagnosticCollector<JavaFileObject> dc = new DiagnosticCollector<>();
- List<JavaSource> files = Arrays.asList(new JavaSource(type1, op, type2));
- comp.getTask(null, null, dc, null, null, files).call();
- if (dc.getDiagnostics().isEmpty() ^ TYPE.compatible(type1, type2)) {
- throw new AssertionError("Unexpected behavior. Type1: " + type1 +
- "; type2: " + type2 +
- "; diagnostics: " + dc.getDiagnostics());
- }
- }
- enum TYPE {
+public class BitWiseOperators extends ComboInstance<BitWiseOperators> {
+
+ enum OperandType implements ComboParameter {
BYTE,
CHAR,
SHORT,
@@ -69,45 +52,57 @@
LONG,
BOOLEAN;
- public static boolean compatible(TYPE op1, TYPE op2) {
+ public static boolean compatible(OperandType op1, OperandType op2) {
return !(op1 == BOOLEAN ^ op2 == BOOLEAN);
}
+
+ @Override
+ public String expand(String optParameter) {
+ return StringUtils.toLowerCase(name());
+ }
}
- enum OPERATION {
+ enum OperatorKind implements ComboParameter {
BITAND("&"),
BITOR("|"),
BITXOR("^");
String op;
- private OPERATION(String op) {
+ OperatorKind(String op) {
this.op = op;
}
- }
-
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "class Test {\n" +
- " public Object test(#TYPE1 var1, #TYPE2 var2) {\n" +
- " return var1 #OP var2;\n" +
- " }\n" +
- "}";
-
- String source;
-
- public JavaSource(TYPE type1, OPERATION op, TYPE type2) {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replaceAll("#TYPE1", StringUtils.toLowerCase(type1.name()))
- .replaceAll("#OP", StringUtils.toLowerCase(op.op))
- .replaceAll("#TYPE2", StringUtils.toLowerCase(type2.name()));
- }
-
@Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
+ public String expand(String optParameter) {
+ return op;
}
}
+ public static void main(String... args) {
+ new ComboTestHelper<BitWiseOperators>()
+ .withArrayDimension("TYPE", (x, type, idx) -> x.opTypes[idx] = type, 2, OperandType.values())
+ .withDimension("OP", OperatorKind.values())
+ .run(BitWiseOperators::new);
+ }
+
+ OperandType[] opTypes = new OperandType[2];
+
+ String template = "class Test {\n" +
+ " public Object test(#{TYPE[0]} var1, #{TYPE[1]} var2) {\n" +
+ " return var1 #{OP} var2;\n" +
+ " }\n" +
+ "}";
+
+ @Override
+ public void doWork() throws IOException {
+ Result<?> res = newCompilationTask()
+ .withSourceFromTemplate(template)
+ .analyze();
+ if (res.hasErrors() == OperandType.compatible(opTypes[0], opTypes[1])) {
+ fail("Unexpected behavior. Type1: " + opTypes[0] +
+ "; type2: " + opTypes[1] +
+ "; " + res.compilationInfo());
+ }
+ }
}
--- a/langtools/test/tools/javac/types/ScopeListenerTest.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/types/ScopeListenerTest.java Mon Sep 14 07:03:04 2015 +0000
@@ -29,6 +29,7 @@
*/
import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Scope.ScopeListenerList;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Types;
@@ -53,20 +54,14 @@
types.membersClosure(syms.stringType, true);
types.membersClosure(syms.stringType, false);
- Field listenersField = Scope.class.getDeclaredField("listeners");
-
- listenersField.setAccessible(true);
-
- int listenerCount =
- ((Collection) listenersField.get(syms.stringType.tsym.members())).size();
+ int listenerCount = listenerCount(syms.stringType.tsym.members());
for (int i = 0; i < 100; i++) {
types.membersClosure(syms.stringType, true);
types.membersClosure(syms.stringType, false);
}
- int newListenerCount
- = ((Collection) listenersField.get(syms.stringType.tsym.members())).size();
+ int newListenerCount = listenerCount(syms.stringType.tsym.members());
if (listenerCount != newListenerCount) {
throw new AssertionError("Orig listener count: " + listenerCount +
@@ -79,4 +74,12 @@
;
}
+ int listenerCount(Scope s) throws ReflectiveOperationException {
+ Field listenersListField = Scope.class.getDeclaredField("listeners");
+ listenersListField.setAccessible(true);
+ Field listenersField = ScopeListenerList.class.getDeclaredField("listeners");
+ listenersField.setAccessible(true);
+ return ((Collection<?>)listenersField.get(listenersListField.get(s))).size();
+ }
+
}
--- a/langtools/test/tools/javac/varargs/7042566/T7042566.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/varargs/7042566/T7042566.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,31 +23,25 @@
/*
* @test
- * @bug 7042566 8006694
+ * @bug 7042566 8006694 8129962
* @summary Unambiguous varargs method calls flagged as ambiguous
* temporarily workaround combo tests are causing time out in several platforms
- * @library ../../lib
+ * @library /tools/javac/lib
* @modules jdk.jdeps/com.sun.tools.classfile
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm T7042566
+ * @build combo.ComboTestHelper
+ * @run main T7042566
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
+import java.io.IOException;
+import java.io.InputStream;
+import javax.tools.JavaFileObject;
-import java.io.File;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Locale;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.ToolProvider;
-
-import com.sun.source.util.JavacTask;
import com.sun.tools.classfile.Instruction;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
@@ -56,145 +50,12 @@
import com.sun.tools.classfile.Method;
import com.sun.tools.javac.util.List;
-public class T7042566
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
-
- VarargsMethod m1;
- VarargsMethod m2;
- TypeConfiguration actuals;
-
- T7042566(TypeConfiguration m1_conf, TypeConfiguration m2_conf,
- TypeConfiguration actuals) {
- this.m1 = new VarargsMethod(m1_conf);
- this.m2 = new VarargsMethod(m2_conf);
- this.actuals = actuals;
- }
-
- @Override
- public void run() {
- int id = checkCount.incrementAndGet();
- final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
- JavaSource source = new JavaSource(id);
- ErrorChecker ec = new ErrorChecker();
- JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), ec,
- null, null, Arrays.asList(source));
- ct.call();
- check(source, ec, id);
- }
-
- void check(JavaSource source, ErrorChecker ec, int id) {
- boolean resolutionError = false;
- VarargsMethod selectedMethod = null;
-
- boolean m1_applicable = m1.isApplicable(actuals);
- boolean m2_applicable = m2.isApplicable(actuals);
-
- if (!m1_applicable && !m2_applicable) {
- resolutionError = true;
- } else if (m1_applicable && m2_applicable) {
- //most specific
- boolean m1_moreSpecific = m1.isMoreSpecificThan(m2);
- boolean m2_moreSpecific = m2.isMoreSpecificThan(m1);
-
- resolutionError = m1_moreSpecific == m2_moreSpecific;
- selectedMethod = m1_moreSpecific ? m1 : m2;
- } else {
- selectedMethod = m1_applicable ?
- m1 : m2;
- }
-
- if (ec.errorFound != resolutionError) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
- "\nExpected resolution error: " + resolutionError +
- "\nFound error: " + ec.errorFound +
- "\nCompiler diagnostics:\n" + ec.printDiags());
- } else if (!resolutionError) {
- verifyBytecode(selectedMethod, source, id);
- }
- }
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
- void verifyBytecode(VarargsMethod selected, JavaSource source, int id) {
- bytecodeCheckCount.incrementAndGet();
- File compiledTest = new File(String.format("Test%d.class", id));
- try {
- ClassFile cf = ClassFile.read(compiledTest);
- Method testMethod = null;
- for (Method m : cf.methods) {
- if (m.getName(cf.constant_pool).equals("test")) {
- testMethod = m;
- break;
- }
- }
- if (testMethod == null) {
- throw new Error("Test method not found");
- }
- Code_attribute ea =
- (Code_attribute)testMethod.attributes.get(Attribute.Code);
- if (testMethod == null) {
- throw new Error("Code attribute for test() method not found");
- }
-
- for (Instruction i : ea.getInstructions()) {
- if (i.getMnemonic().equals("invokevirtual")) {
- int cp_entry = i.getUnsignedShort(1);
- CONSTANT_Methodref_info methRef =
- (CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry);
- String type = methRef.getNameAndTypeInfo().getType();
- String sig = selected.parameterTypes.bytecodeSigStr;
- if (!type.contains(sig)) {
- throw new Error("Unexpected type method call: " +
- type + "" +
- "\nfound: " + sig +
- "\n" + source.getCharContent(true));
- }
- break;
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- throw new Error("error reading " + compiledTest +": " + e);
- }
- }
-
- class JavaSource extends SimpleJavaFileObject {
-
- static final String source_template = "class Test#ID {\n" +
- " #V1\n" +
- " #V2\n" +
- " void test() { m(#E); }\n" +
- "}";
-
- String source;
-
- public JavaSource(int id) {
- super(URI.create(String.format("myfo:/Test%d.java", id)),
- JavaFileObject.Kind.SOURCE);
- source = source_template.replaceAll("#V1", m1.toString())
- .replaceAll("#V2", m2.toString())
- .replaceAll("#E", actuals.expressionListStr)
- .replaceAll("#ID", String.valueOf(id));
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
- }
-
- public static void main(String... args) throws Exception {
- for (TypeConfiguration tconf1 : TypeConfiguration.values()) {
- for (TypeConfiguration tconf2 : TypeConfiguration.values()) {
- for (TypeConfiguration tconf3 : TypeConfiguration.values()) {
- pool.execute(new T7042566(tconf1, tconf2, tconf3));
- }
- }
- }
-
- outWriter.println("Bytecode checks made: " + bytecodeCheckCount.get());
- checkAfterExec();
- }
+public class T7042566 extends ComboInstance<T7042566> {
enum TypeKind {
OBJECT("Object", "(Object)null", "Ljava/lang/Object;"),
@@ -216,7 +77,7 @@
}
}
- enum TypeConfiguration {
+ enum TypeConfiguration implements ComboParameter {
A(TypeKind.OBJECT),
B(TypeKind.STRING),
AA(TypeKind.OBJECT, TypeKind.OBJECT),
@@ -237,7 +98,7 @@
String parameterListStr;
String bytecodeSigStr;
- private TypeConfiguration(TypeKind... typeKindList) {
+ TypeConfiguration(TypeKind... typeKindList) {
this.typeKindList = List.from(typeKindList);
expressionListStr = asExpressionList();
parameterListStr = asParameterList();
@@ -284,6 +145,11 @@
}
return buf.toString();
}
+
+ @Override
+ public String expand(String optParameter) {
+ return expressionListStr;
+ }
}
static class VarargsMethod {
@@ -333,31 +199,119 @@
}
}
- static class ErrorChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
+ public static void main(String[] args) {
+ new ComboTestHelper<T7042566>()
+ .withArrayDimension("SIG", (x, sig, idx) -> x.methodSignatures[idx] = sig, 2, TypeConfiguration.values())
+ .withDimension("ACTUALS", (x, actuals) -> x.actuals = actuals, TypeConfiguration.values())
+ .run(T7042566::new, T7042566::setup);
+ }
- boolean errorFound;
- List<String> errDiags = List.nil();
+ VarargsMethod m1;
+ VarargsMethod m2;
+ TypeConfiguration[] methodSignatures = new TypeConfiguration[2];
+ TypeConfiguration actuals;
+
+ void setup() {
+ this.m1 = new VarargsMethod(methodSignatures[0]);
+ this.m2 = new VarargsMethod(methodSignatures[1]);
+ }
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
- errDiags = errDiags
- .append(diagnostic.getMessage(Locale.getDefault()));
- errorFound = true;
- }
- }
+ final String source_template = "class Test {\n" +
+ " #{METH.1}\n" +
+ " #{METH.2}\n" +
+ " void test() { m(#{ACTUALS}); }\n" +
+ "}";
- String printDiags() {
- StringBuilder buf = new StringBuilder();
- for (String s : errDiags) {
- buf.append(s);
- buf.append("\n");
- }
- return buf.toString();
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withSourceFromTemplate(source_template, this::getMethodDecl)
+ .generate());
+ }
+
+ ComboParameter getMethodDecl(String parameterName) {
+ switch (parameterName) {
+ case "METH": return optParameter -> {
+ return optParameter.equals("1") ?
+ m1.toString() : m2.toString();
+ };
+ default:
+ return null;
}
}
- //number of bytecode checks made while running combo tests
- static AtomicInteger bytecodeCheckCount = new AtomicInteger();
+ void check(Result<Iterable<? extends JavaFileObject>> res) {
+ boolean resolutionError = false;
+ VarargsMethod selectedMethod = null;
+
+ boolean m1_applicable = m1.isApplicable(actuals);
+ boolean m2_applicable = m2.isApplicable(actuals);
+
+ if (!m1_applicable && !m2_applicable) {
+ resolutionError = true;
+ } else if (m1_applicable && m2_applicable) {
+ //most specific
+ boolean m1_moreSpecific = m1.isMoreSpecificThan(m2);
+ boolean m2_moreSpecific = m2.isMoreSpecificThan(m1);
+
+ resolutionError = m1_moreSpecific == m2_moreSpecific;
+ selectedMethod = m1_moreSpecific ? m1 : m2;
+ } else {
+ selectedMethod = m1_applicable ?
+ m1 : m2;
+ }
+
+ if (res.hasErrors() != resolutionError) {
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
+ "\nExpected resolution error: " + resolutionError +
+ "\nFound error: " + res.hasErrors());
+ } else if (!resolutionError) {
+ verifyBytecode(res, selectedMethod);
+ }
+ }
+ void verifyBytecode(Result<Iterable<? extends JavaFileObject>> res, VarargsMethod selected) {
+ try (InputStream is = res.get().iterator().next().openInputStream()) {
+ ClassFile cf = ClassFile.read(is);
+ Method testMethod = null;
+ for (Method m : cf.methods) {
+ if (m.getName(cf.constant_pool).equals("test")) {
+ testMethod = m;
+ break;
+ }
+ }
+ if (testMethod == null) {
+ fail("Test method not found");
+ return;
+ }
+ Code_attribute ea =
+ (Code_attribute)testMethod.attributes.get(Attribute.Code);
+ if (testMethod == null) {
+ fail("Code attribute for test() method not found");
+ return;
+ }
+
+ for (Instruction i : ea.getInstructions()) {
+ if (i.getMnemonic().equals("invokevirtual")) {
+ int cp_entry = i.getUnsignedShort(1);
+ CONSTANT_Methodref_info methRef =
+ (CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry);
+ String type = methRef.getNameAndTypeInfo().getType();
+ String sig = selected.parameterTypes.bytecodeSigStr;
+ if (!type.contains(sig)) {
+ fail("Unexpected type method call: " +
+ type + "" +
+ "\nfound: " + sig +
+ "\n" + res.compilationInfo());
+ return;
+ }
+ break;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("error reading classfile; " + res.compilationInfo() +": " + e);
+ }
+ }
}
--- a/langtools/test/tools/javac/varargs/warning/Warn4.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/varargs/warning/Warn4.java Mon Sep 14 07:03:04 2015 +0000
@@ -23,40 +23,39 @@
/**
* @test
- * @bug 6945418 6993978 8006694 7196160
+ * @bug 6945418 6993978 8006694 7196160 8129962
* @summary Project Coin: Simplified Varargs Method Invocation
* temporarily workaround combo tests are causing time out in several platforms
- * @author mcimadamore
- * @library ../../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
- * @run main/othervm Warn4
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main Warn4
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
-import java.net.URI;
-import java.util.Arrays;
+import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
+import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.ToolProvider;
-import com.sun.source.util.JavacTask;
-public class Warn4
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
+
+public class Warn4 extends ComboInstance<Warn4> {
final static Warning[] error = null;
final static Warning[] none = new Warning[] {};
final static Warning[] vararg = new Warning[] { Warning.VARARGS };
final static Warning[] unchecked = new Warning[] { Warning.UNCHECKED };
- final static Warning[] both =
- new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
+ final static Warning[] both = new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
enum Warning {
UNCHECKED("generic.array.creation"),
@@ -105,7 +104,7 @@
}
}
- enum TrustMe {
+ enum TrustMe implements ComboParameter {
DONT_TRUST(""),
TRUST("@java.lang.SafeVarargs");
@@ -114,9 +113,14 @@
TrustMe(String anno) {
this.anno = anno;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return anno;
+ }
}
- enum ModifierKind {
+ enum ModifierKind implements ComboParameter {
NONE(" "),
FINAL("final "),
STATIC("static "),
@@ -127,9 +131,14 @@
ModifierKind(String mod) {
this.mod = mod;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return mod;
+ }
}
- enum SuppressLevel {
+ enum SuppressLevel implements ComboParameter {
NONE(""),
UNCHECKED("unchecked");
@@ -139,21 +148,22 @@
this.lint = lint;
}
- String getSuppressAnno() {
+ @Override
+ public String expand(String optParameter) {
return "@SuppressWarnings(\"" + lint + "\")";
}
}
- enum Signature {
- UNBOUND("void #name(List<?>#arity arg) { #body }",
+ enum Signature implements ComboParameter {
+ UNBOUND("void #NAME(List<?>#ARITY arg) { #BODY }",
new Warning[][] {none, none, none, none, error}),
- INVARIANT_TVAR("<Z> void #name(List<Z>#arity arg) { #body }",
+ INVARIANT_TVAR("<Z> void #NAME(List<Z>#ARITY arg) { #BODY }",
new Warning[][] {both, both, error, both, error}),
- TVAR("<Z> void #name(Z#arity arg) { #body }",
+ TVAR("<Z> void #NAME(Z#ARITY arg) { #BODY }",
new Warning[][] {both, both, both, both, vararg}),
- INVARIANT("void #name(List<String>#arity arg) { #body }",
+ INVARIANT("void #NAME(List<String>#ARITY arg) { #BODY }",
new Warning[][] {error, error, error, both, error}),
- UNPARAMETERIZED("void #name(String#arity arg) { #body }",
+ UNPARAMETERIZED("void #NAME(String#ARITY arg) { #BODY }",
new Warning[][] {error, error, error, error, none});
String template;
@@ -177,130 +187,85 @@
return warnings[other.ordinal()] == vararg ||
warnings[other.ordinal()] == both;
}
+
+ @Override
+ public String expand(String optParameter) {
+ if (optParameter.equals("CLIENT")) {
+ return template.replaceAll("#ARITY", "")
+ .replaceAll("#NAME", "test")
+ .replaceAll("#BODY", "m(arg)");
+ } else {
+ return template.replaceAll("#ARITY", "...")
+ .replaceAll("#NAME", "m")
+ .replaceAll("#BODY", "");
+ }
+ }
}
- public static void main(String... args) throws Exception {
- for (SourceLevel sourceLevel : SourceLevel.values()) {
- for (TrustMe trustMe : TrustMe.values()) {
- for (SuppressLevel suppressLevelClient : SuppressLevel.values()) {
- for (SuppressLevel suppressLevelDecl : SuppressLevel.values()) {
- for (ModifierKind modKind : ModifierKind.values()) {
- for (Signature vararg_meth : Signature.values()) {
- for (Signature client_meth : Signature.values()) {
- if (vararg_meth.isApplicableTo(client_meth)) {
- pool.execute(new Warn4(sourceLevel,
- trustMe,
- suppressLevelClient,
- suppressLevelDecl,
- modKind,
- vararg_meth,
- client_meth));
- }
- }
- }
- }
- }
- }
- }
- }
-
- checkAfterExec();
+ public static void main(String... args) {
+ new ComboTestHelper<Warn4>()
+ .withFilter(Warn4::badTestFilter)
+ .withDimension("SOURCE", (x, level) -> x.sourceLevel = level, SourceLevel.values())
+ .withDimension("TRUSTME", (x, trustme) -> x.trustMe = trustme, TrustMe.values())
+ .withArrayDimension("SUPPRESS", (x, suppress, idx) -> x.suppress[idx] = suppress, 2, SuppressLevel.values())
+ .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values())
+ .withArrayDimension("MTH", (x, sig, idx) -> x.sigs[idx] = sig, 2, Signature.values())
+ .run(Warn4::new);
}
SourceLevel sourceLevel;
TrustMe trustMe;
- SuppressLevel suppressLevelClient;
- SuppressLevel suppressLevelDecl;
+ SuppressLevel[] suppress = new SuppressLevel[2];
ModifierKind modKind;
- Signature vararg_meth;
- Signature client_meth;
- DiagnosticChecker diagChecker;
+ Signature[] sigs = new Signature[2];
- public Warn4(SourceLevel sourceLevel, TrustMe trustMe,
- SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl,
- ModifierKind modKind, Signature vararg_meth, Signature client_meth) {
- this.sourceLevel = sourceLevel;
- this.trustMe = trustMe;
- this.suppressLevelClient = suppressLevelClient;
- this.suppressLevelDecl = suppressLevelDecl;
- this.modKind = modKind;
- this.vararg_meth = vararg_meth;
- this.client_meth = client_meth;
- this.diagChecker = new DiagnosticChecker();
+ boolean badTestFilter() {
+ return sigs[0].isApplicableTo(sigs[1]);
}
+ final String template = "import java.util.List;\n" +
+ "class Test {\n" +
+ " #{TRUSTME} #{SUPPRESS[0]} #{MOD} #{MTH[0].VARARG}\n" +
+ " #{SUPPRESS[1]} #{MTH[1].CLIENT}\n" +
+ "}";
+
@Override
- public void run() {
- int id = checkCount.incrementAndGet();
- final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
- JavaSource source = new JavaSource(id);
- JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
- Arrays.asList("-Xlint:unchecked", "-source", sourceLevel.sourceKey),
- null, Arrays.asList(source));
- ct.call(); //to get mandatory notes
- check(source, new boolean[] {vararg_meth.giveUnchecked(client_meth),
- vararg_meth.giveVarargs(client_meth)});
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withOption("-Xlint:unchecked")
+ .withOption("-source")
+ .withOption(sourceLevel.sourceKey)
+ .withSourceFromTemplate(template)
+ .analyze());
}
- void check(JavaSource source, boolean[] warnArr) {
+ void check(Result<?> res) {
+ boolean[] warnArr = new boolean[] {sigs[0].giveUnchecked(sigs[1]),
+ sigs[0].giveVarargs(sigs[1])};
+
+ Set<Warning> warnings = new HashSet<>();
+ for (Diagnostic<? extends JavaFileObject> d : res.diagnosticsForKind(Kind.MANDATORY_WARNING)) {
+ if (d.getCode().contains(Warning.VARARGS.key)) {
+ warnings.add(Warning.VARARGS);
+ } else if(d.getCode().contains(Warning.UNCHECKED.key)) {
+ warnings.add(Warning.UNCHECKED);
+ }
+ }
+
boolean badOutput = false;
for (Warning wkind : Warning.values()) {
boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel,
- suppressLevelClient, suppressLevelDecl, modKind);
+ suppress[1], suppress[0], modKind);
badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) !=
- diagChecker.warnings.contains(wkind);
+ warnings.contains(wkind);
}
if (badOutput) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
"\nExpected unchecked warning: " + warnArr[0] +
"\nExpected unsafe vararg warning: " + warnArr[1] +
- "\nWarnings: " + diagChecker.warnings +
+ "\nWarnings: " + warnings +
"\nSource level: " + sourceLevel);
}
}
-
- class JavaSource extends SimpleJavaFileObject {
-
- String source;
-
- public JavaSource(int id) {
- super(URI.create(String.format("myfo:/Test%d.java", id)),
- JavaFileObject.Kind.SOURCE);
- String meth1 = vararg_meth.template.replace("#arity", "...");
- meth1 = meth1.replace("#name", "m");
- meth1 = meth1.replace("#body", "");
- meth1 = trustMe.anno + "\n" + suppressLevelDecl.getSuppressAnno() +
- modKind.mod + meth1;
- String meth2 = client_meth.template.replace("#arity", "");
- meth2 = meth2.replace("#name", "test");
- meth2 = meth2.replace("#body", "m(arg);");
- meth2 = suppressLevelClient.getSuppressAnno() + meth2;
- source = String.format("import java.util.List;\n" +
- "class Test%s {\n %s \n %s \n } \n", id, meth1, meth2);
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
- }
- }
-
- static class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- Set<Warning> warnings = new HashSet<>();
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING ||
- diagnostic.getKind() == Diagnostic.Kind.WARNING) {
- if (diagnostic.getCode().contains(Warning.VARARGS.key)) {
- warnings.add(Warning.VARARGS);
- } else if(diagnostic.getCode().contains(Warning.UNCHECKED.key)) {
- warnings.add(Warning.UNCHECKED);
- }
- }
- }
- }
-
}
--- a/langtools/test/tools/javac/varargs/warning/Warn5.java Mon Sep 14 07:02:50 2015 +0200
+++ b/langtools/test/tools/javac/varargs/warning/Warn5.java Mon Sep 14 07:03:04 2015 +0000
@@ -26,29 +26,30 @@
* @bug 6993978 7097436 8006694 7196160
* @summary Project Coin: Annotation to reduce varargs warnings
* temporarily workaround combo tests are causing time out in several platforms
- * @author mcimadamore
- * @library ../../lib
- * @modules jdk.compiler
- * @build JavacTestingAbstractThreadedTest
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
* @run main/othervm Warn5
*/
-// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
-// see JDK-8006746
-
-import java.net.URI;
-import java.util.Arrays;
+import java.io.IOException;
import java.util.EnumSet;
import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
+import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.ToolProvider;
-import com.sun.source.util.JavacTask;
-public class Warn5
- extends JavacTestingAbstractThreadedTest
- implements Runnable {
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask.Result;
+import combo.ComboTestHelper;
+
+
+public class Warn5 extends ComboInstance<Warn5> {
enum XlintOption {
NONE("none"),
@@ -65,7 +66,7 @@
}
}
- enum TrustMe {
+ enum TrustMe implements ComboParameter {
DONT_TRUST(""),
TRUST("@java.lang.SafeVarargs");
@@ -74,20 +75,26 @@
TrustMe(String anno) {
this.anno = anno;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return anno;
+ }
}
- enum SuppressLevel {
+ enum SuppressLevel implements ComboParameter {
NONE,
VARARGS;
- String getSuppressAnno() {
+ @Override
+ public String expand(String optParameter) {
return this == VARARGS ?
"@SuppressWarnings(\"varargs\")" :
"";
}
}
- enum ModifierKind {
+ enum ModifierKind implements ComboParameter {
NONE(""),
FINAL("final"),
STATIC("static"),
@@ -98,9 +105,14 @@
ModifierKind(String mod) {
this.mod = mod;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return mod;
+ }
}
- enum MethodKind {
+ enum MethodKind implements ComboParameter {
METHOD("void m"),
CONSTRUCTOR("Test");
@@ -109,6 +121,11 @@
MethodKind(String name) {
this.name = name;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return name;
+ }
}
enum SourceLevel {
@@ -123,11 +140,11 @@
}
}
- enum SignatureKind {
- VARARGS_X("#K <X>#N(X... x)", false, true),
- VARARGS_STRING("#K #N(String... x)", true, true),
- ARRAY_X("#K <X>#N(X[] x)", false, false),
- ARRAY_STRING("#K #N(String[] x)", true, false);
+ enum SignatureKind implements ComboParameter {
+ VARARGS_X("<X>#{NAME}(X... x)", false, true),
+ VARARGS_STRING("#{NAME}(String... x)", true, true),
+ ARRAY_X("<X>#{NAME}(X[] x)", false, false),
+ ARRAY_STRING("#{NAME}(String[] x)", true, false);
String stub;
boolean isReifiableArg;
@@ -139,14 +156,13 @@
this.isVarargs = isVarargs;
}
- String getSignature(ModifierKind modKind, MethodKind methKind) {
- return methKind != MethodKind.CONSTRUCTOR ?
- stub.replace("#K", modKind.mod).replace("#N", methKind.name) :
- stub.replace("#K", "").replace("#N", methKind.name);
+ @Override
+ public String expand(String optParameter) {
+ return stub;
}
}
- enum BodyKind {
+ enum BodyKind implements ComboParameter {
ASSIGN("Object o = x;", true),
CAST("Object o = (Object)x;", true),
METH("test(x);", true),
@@ -162,82 +178,84 @@
this.body = body;
this.hasAliasing = hasAliasing;
}
+
+ @Override
+ public String expand(String optParameter) {
+ return body;
+ }
}
enum WarningKind {
- UNSAFE_BODY,
- UNSAFE_DECL,
- MALFORMED_SAFEVARARGS,
- REDUNDANT_SAFEVARARGS;
+ UNSAFE_BODY("compiler.warn.varargs.unsafe.use.varargs.param"),
+ UNSAFE_DECL("compiler.warn.unchecked.varargs.non.reifiable.type"),
+ MALFORMED_SAFEVARARGS("compiler.err.varargs.invalid.trustme.anno"),
+ REDUNDANT_SAFEVARARGS("compiler.warn.varargs.redundant.trustme.anno");
+
+ String code;
+
+ WarningKind(String code) {
+ this.code = code;
+ }
+ }
+
+ public static void main(String[] args) {
+ new ComboTestHelper<Warn5>()
+ .withFilter(Warn5::badTestFilter)
+ .withDimension("SOURCE", (x, level) -> x.sourceLevel = level, SourceLevel.values())
+ .withDimension("LINT", (x, lint) -> x.xlint = lint, XlintOption.values())
+ .withDimension("TRUSTME", (x, trustme) -> x.trustMe = trustme, TrustMe.values())
+ .withDimension("SUPPRESS", (x, suppress) -> x.suppressLevel = suppress, SuppressLevel.values())
+ .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values())
+ .withDimension("NAME", (x, name) -> x.methKind = name, MethodKind.values())
+ .withDimension("SIG", (x, sig) -> x.sig = sig, SignatureKind.values())
+ .withDimension("BODY", (x, body) -> x.body = body, BodyKind.values())
+ .run(Warn5::new);
}
- public static void main(String... args) throws Exception {
- for (SourceLevel sourceLevel : SourceLevel.values()) {
- for (XlintOption xlint : XlintOption.values()) {
- for (TrustMe trustMe : TrustMe.values()) {
- for (SuppressLevel suppressLevel : SuppressLevel.values()) {
- for (ModifierKind modKind : ModifierKind.values()) {
- for (MethodKind methKind : MethodKind.values()) {
- for (SignatureKind sig : SignatureKind.values()) {
- for (BodyKind body : BodyKind.values()) {
- pool.execute(new Warn5(sourceLevel,
- xlint, trustMe, suppressLevel,
- modKind, methKind, sig, body));
- }
- }
- }
- }
+ SourceLevel sourceLevel;
+ XlintOption xlint;
+ TrustMe trustMe;
+ SuppressLevel suppressLevel;
+ ModifierKind modKind;
+ MethodKind methKind;
+ SignatureKind sig;
+ BodyKind body;
+
+ boolean badTestFilter() {
+ return (methKind != MethodKind.CONSTRUCTOR || modKind == ModifierKind.NONE);
+ }
+
+ String template = "import com.sun.tools.javac.api.*;\n" +
+ "import java.util.List;\n" +
+ "class Test {\n" +
+ " static void test(Object o) {}\n" +
+ " static void testArr(Object[] o) {}\n" +
+ " #{TRUSTME} #{SUPPRESS} #{MOD} #{SIG} { #{BODY} }\n" +
+ "}\n";
+
+ @Override
+ public void doWork() throws IOException {
+ check(newCompilationTask()
+ .withOption(xlint.getXlintOption())
+ .withOption("-source")
+ .withOption(sourceLevel.sourceKey)
+ .withSourceFromTemplate(template)
+ .analyze());
+ }
+
+ void check(Result<?> res) {
+
+ EnumSet<WarningKind> foundWarnings = EnumSet.noneOf(WarningKind.class);
+ for (Diagnostic.Kind kind : new Kind[] { Kind.ERROR, Kind.MANDATORY_WARNING, Kind.WARNING}) {
+ for (Diagnostic<? extends JavaFileObject> diag : res.diagnosticsForKind(kind)) {
+ for (WarningKind wk : WarningKind.values()) {
+ if (wk.code.equals(diag.getCode())) {
+ foundWarnings.add(wk);
}
}
}
}
- checkAfterExec(false);
- }
-
- final SourceLevel sourceLevel;
- final XlintOption xlint;
- final TrustMe trustMe;
- final SuppressLevel suppressLevel;
- final ModifierKind modKind;
- final MethodKind methKind;
- final SignatureKind sig;
- final BodyKind body;
- final JavaSource source;
- final DiagnosticChecker dc;
-
- public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe,
- SuppressLevel suppressLevel, ModifierKind modKind,
- MethodKind methKind, SignatureKind sig, BodyKind body) {
- this.sourceLevel = sourceLevel;
- this.xlint = xlint;
- this.trustMe = trustMe;
- this.suppressLevel = suppressLevel;
- this.modKind = modKind;
- this.methKind = methKind;
- this.sig = sig;
- this.body = body;
- this.source = new JavaSource();
- this.dc = new DiagnosticChecker();
- }
-
- @Override
- public void run() {
- final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
- JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc,
- Arrays.asList(xlint.getXlintOption(),
- "-source", sourceLevel.sourceKey),
- null, Arrays.asList(source));
- try {
- ct.analyze();
- } catch (Throwable t) {
- processException(t);
- }
- check();
- }
-
- void check() {
-
EnumSet<WarningKind> expectedWarnings =
EnumSet.noneOf(WarningKind.class);
@@ -284,77 +302,14 @@
expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS);
}
- if (!expectedWarnings.containsAll(dc.warnings) ||
- !dc.warnings.containsAll(expectedWarnings)) {
- throw new Error("invalid diagnostics for source:\n" +
- source.getCharContent(true) +
+ if (!expectedWarnings.containsAll(foundWarnings) ||
+ !foundWarnings.containsAll(expectedWarnings)) {
+ fail("invalid diagnostics for source:\n" +
+ res.compilationInfo() +
"\nOptions: " + xlint.getXlintOption() +
"\nSource Level: " + sourceLevel +
"\nExpected warnings: " + expectedWarnings +
- "\nFound warnings: " + dc.warnings);
- }
- }
-
- class JavaSource extends SimpleJavaFileObject {
-
- String template = "import com.sun.tools.javac.api.*;\n" +
- "import java.util.List;\n" +
- "class Test {\n" +
- " static void test(Object o) {}\n" +
- " static void testArr(Object[] o) {}\n" +
- " #T \n #S #M { #B }\n" +
- "}\n";
-
- String source;
-
- public JavaSource() {
- super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
- source = template.replace("#T", trustMe.anno).
- replace("#S", suppressLevel.getSuppressAnno()).
- replace("#M", sig.getSignature(modKind, methKind)).
- replace("#B", body.body);
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return source;
+ "\nFound warnings: " + foundWarnings);
}
}
-
- class DiagnosticChecker
- implements javax.tools.DiagnosticListener<JavaFileObject> {
-
- EnumSet<WarningKind> warnings = EnumSet.noneOf(WarningKind.class);
-
- public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
- if (diagnostic.getKind() == Diagnostic.Kind.WARNING) {
- if (diagnostic.getCode().
- contains("unsafe.use.varargs.param")) {
- setWarning(WarningKind.UNSAFE_BODY);
- } else if (diagnostic.getCode().
- contains("redundant.trustme")) {
- setWarning(WarningKind.REDUNDANT_SAFEVARARGS);
- }
- } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING &&
- diagnostic.getCode().
- contains("varargs.non.reifiable.type")) {
- setWarning(WarningKind.UNSAFE_DECL);
- } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
- diagnostic.getCode().contains("invalid.trustme")) {
- setWarning(WarningKind.MALFORMED_SAFEVARARGS);
- }
- }
-
- void setWarning(WarningKind wk) {
- if (!warnings.add(wk)) {
- throw new AssertionError("Duplicate warning of kind " +
- wk + " in source:\n" + source);
- }
- }
-
- boolean hasWarning(WarningKind wk) {
- return warnings.contains(wk);
- }
- }
-
}
--- a/make/Init.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/make/Init.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -253,6 +253,7 @@
main: $(INIT_TARGETS)
ifneq ($(SEQUENTIAL_TARGETS)$(PARALLEL_TARGETS), )
$(call RotateLogFiles)
+ $(call PrepareFailureLogs)
$(BUILD_LOG_WRAPPER) $(PRINTF) "Building $(TARGET_DESCRIPTION)\n"
ifneq ($(SEQUENTIAL_TARGETS), )
# Don't touch build output dir since we might be cleaning. That
@@ -266,10 +267,13 @@
$(call PrepareSmartJavac)
( cd $(TOPDIR) && \
$(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) $(OUTPUT_SYNC_FLAG) \
- -j $(JOBS) -f make/Main.gmk $(USER_MAKE_VARS) \
- $(PARALLEL_TARGETS) || \
- ( exitcode=$$? && $(BUILD_LOG_WRAPPER) $(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" && \
- $(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors \n\n" && exit $$exitcode ) )
+ -j $(JOBS) -f make/Main.gmk $(USER_MAKE_VARS) \
+ $(PARALLEL_TARGETS) || \
+ ( exitcode=$$? && $(BUILD_LOG_WRAPPER) \
+ $(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" && \
+ cd $(TOPDIR) && $(MAKE) $(MAKE_ARGS) -j 1 -f make/Init.gmk \
+ HAS_SPEC=true on-failure ; \
+ exit $$exitcode ) )
$(call CleanupSmartJavac)
$(call StopGlobalTimer)
$(call ReportBuildTimes)
@@ -277,5 +281,25 @@
$(BUILD_LOG_WRAPPER) $(PRINTF) "Finished building $(TARGET_DESCRIPTION)\n"
endif
- .PHONY: print-targets print-modules reconfigure main
+ on-failure:
+ ifneq ($(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*), )
+ $(PRINTF) "=== Output from failing command(s) repeated here ===\n"
+ $(foreach logfile, $(sort $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*)), \
+ $(PRINTF) "* For target $(notdir $(basename $(logfile))):\n" $(NEWLINE) \
+ $(CAT) $(logfile) | $(GREP) -v -e "^Note: including file:" $(NEWLINE) \
+ )
+ $(PRINTF) "=== End of repeated output ===\n"
+ endif
+ if $(GREP) -q "recipe for target .* failed" $(BUILD_LOG) 2> /dev/null; then \
+ $(PRINTF) "=== Make failure sequence repeated here ===\n" ; \
+ $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \
+ $(PRINTF) "=== End of repeated output ===\n" ; \
+ $(PRINTF) "Hint: Try searching the build log for the name of the first failed target.\n" ; \
+ else \
+ $(PRINTF) "No indication of failed target found.\n" ; \
+ $(PRINTF) "Hint: Try searching the build log for '] Error'.\n" ; \
+ fi
+ $(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors.\n\n"
+
+ .PHONY: print-targets print-modules reconfigure main on-failure
endif
--- a/make/InitSupport.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/make/InitSupport.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -318,6 +318,11 @@
)
endef
+ define PrepareFailureLogs
+ $(RM) -r $(MAKESUPPORT_OUTPUTDIR)/failure-logs 2> /dev/null
+ $(MKDIR) -p $(MAKESUPPORT_OUTPUTDIR)/failure-logs
+ endef
+
# Remove any javac server logs and port files. This
# prevents a new make run to reuse the previous servers.
define PrepareSmartJavac
--- a/make/common/JavaCompilation.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/make/common/JavaCompilation.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -563,18 +563,19 @@
$(MKDIR) -p $$(@D) $$(dir $$($1_SJAVAC_PORTFILE))
$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
$(ECHO) Compiling $1
- ($$($1_JVM) $$($1_SJAVAC) \
- $$($1_REMOTE) \
- -j 1 \
- --permit-unidentified-artifacts \
- --permit-sources-without-package \
- --compare-found-sources $$($1_BIN)/_the.$1_batch.tmp \
- --log=$(LOG_LEVEL) \
- $$($1_SJAVAC_ARGS) \
- $$($1_FLAGS) \
- $$($1_HEADERS_ARG) \
- -d $$($1_BIN) && \
- $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch)
+ $(call LogFailures, $$($1_BIN)/_the.$1_batch.log, $1, \
+ $$($1_JVM) $$($1_SJAVAC) \
+ $$($1_REMOTE) \
+ -j 1 \
+ --permit-unidentified-artifacts \
+ --permit-sources-without-package \
+ --compare-found-sources $$($1_BIN)/_the.$1_batch.tmp \
+ --log=$(LOG_LEVEL) \
+ $$($1_SJAVAC_ARGS) \
+ $$($1_FLAGS) \
+ $$($1_HEADERS_ARG) \
+ -d $$($1_BIN)) && \
+ $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch
# Create a pubapi file that only changes when the pubapi changes. Dependent
# compilations can use this file to only get recompiled when pubapi has changed.
# Grep returns 1 if no matching lines are found. Do not fail for this.
@@ -619,11 +620,11 @@
$(RM) $$($1_BIN)/_the.$1_batch $$($1_BIN)/_the.$1_batch.tmp
$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
$(ECHO) Compiling `$(WC) $$($1_BIN)/_the.$1_batch.tmp | $(TR) -s ' ' | $(CUT) -f 2 -d ' '` files for $1
- ($$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) \
- -implicit:none \
- -d $$($1_BIN) $$($1_HEADERS_ARG) @$$($1_BIN)/_the.$1_batch.tmp && \
- $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch)
-
+ $(call LogFailures, $$($1_BIN)/_the.$1_batch.log, $1, \
+ $$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) \
+ -implicit:none \
+ -d $$($1_BIN) $$($1_HEADERS_ARG) @$$($1_BIN)/_the.$1_batch.tmp) && \
+ $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch
endif
# Add all targets to main variable
--- a/make/common/MakeBase.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/make/common/MakeBase.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -755,6 +755,20 @@
$(call DependOnVariableHelper,$(strip $1),$(strip $2))
################################################################################
+# Failure logging support macros. These are supposed to be used by the Setup*
+# compilation macros.
+#
+# LogFailures will run a command and store a copy of output in a specified file.
+# If the command succeeds, the file is deleted, otherwise it is moved to the
+# failure-logs directory.
+# Param 1 - The log file of the failed command
+# Param 2 - A compact but representative name to describe this command
+# Param 3 - Command to run
+LogFailures = \
+ ( ($(BASH) $(SRC_ROOT)/common/bin/logger.sh $1 $3 && $(RM) $1) || \
+ (exitcode=$(DOLLAR)$(DOLLAR)? && $(MV) $1 $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(strip $2).log && exit $(DOLLAR)$(DOLLAR)exitcode) )
+
+################################################################################
# Find lib dir for module
# Param 1 - module name
ifeq ($(OPENJDK_TARGET_OS_TYPE), unix)
--- a/make/common/NativeCompilation.gmk Mon Sep 14 07:02:50 2015 +0200
+++ b/make/common/NativeCompilation.gmk Mon Sep 14 07:03:04 2015 +0000
@@ -201,23 +201,25 @@
$$($1_$2_OBJ) : $2 $$($1_COMPILE_VARDEPS_FILE) | $$($1_BUILD_INFO)
$(ECHO) $(LOG_INFO) "Compiling $$(notdir $2) (for $$(notdir $$($1_TARGET)))"
ifneq ($(TOOLCHAIN_TYPE), microsoft)
- # The Solaris studio compiler doesn't output the full path to the object file in the
- # generated deps files. Fixing it with sed. If compiling assembly, don't try this.
ifeq ($(TOOLCHAIN_TYPE)$$(filter %.s,$2), solstudio)
- $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP).tmp $(CC_OUT_OPTION)$$($1_$2_OBJ) $2
+ # The Solaris studio compiler doesn't output the full path to the object file in the
+ # generated deps files. Fixing it with sed. If compiling assembly, don't try this.
+ $(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \
+ $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP).tmp $(CC_OUT_OPTION)$$($1_$2_OBJ) $2)
$(SED) 's|^$$(@F):|$$@:|' $$($1_$2_DEP).tmp > $$($1_$2_DEP)
else
- $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP) $(CC_OUT_OPTION)$$($1_$2_OBJ) $2
+ $(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \
+ $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP) $(CC_OUT_OPTION)$$($1_$2_OBJ) $2)
endif
- endif
- # The Visual Studio compiler lacks a feature for generating make dependencies, but by
- # setting -showIncludes, all included files are printed. These are filtered out and
- # parsed into make dependences.
- ifeq ($(TOOLCHAIN_TYPE), microsoft)
- ($$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \
- $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 ; echo $$$$? > $$($1_$2_DEP).exitvalue) \
+ else
+ # The Visual Studio compiler lacks a feature for generating make dependencies, but by
+ # setting -showIncludes, all included files are printed. These are filtered out and
+ # parsed into make dependences.
+ ($(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \
+ $$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \
+ $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) ; echo $$$$? > $$($1_$2_DEP).exitvalue) \
| $(TEE) $$($1_$2_DEP).raw | $(GREP) -v -e "^Note: including file:" \
- -e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \
+ -e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \
exit `cat $$($1_$2_DEP).exitvalue`
$(RM) $$($1_$2_DEP).exitvalue
($(ECHO) $$@: \\ \
@@ -694,10 +696,11 @@
$$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \
$$($1_DEBUGINFO_EXTRA_DEPS) $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Linking $$($1_BASENAME)"
- $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
+ $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \
+ $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
$(LD_OUT_OPTION)$$@ \
$$($1_EXPECTED_OBJS) $$($1_RES) \
- $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+ $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX))
$$($1_CREATE_DEBUGINFO_CMDS)
# Touch target to make sure it has a later time stamp than the debug
# symbol files to avoid unnecessary relinking on rebuild.
@@ -716,8 +719,9 @@
# Generating a static library, ie object file archive.
$$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)"
- $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \
- $$($1_RES) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+ $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \
+ $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \
+ $$($1_RES) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX))
endif
ifneq (,$$($1_PROGRAM))
@@ -733,10 +737,11 @@
$$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_MANIFEST) \
$$($1_DEBUGINFO_EXTRA_DEPS) $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Linking executable $$($1_BASENAME)"
- $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
- $(EXE_OUT_OPTION)$$($1_TARGET) \
- $$($1_EXPECTED_OBJS) $$($1_RES) \
- $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+ $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \
+ $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
+ $(EXE_OUT_OPTION)$$($1_TARGET) \
+ $$($1_EXPECTED_OBJS) $$($1_RES) \
+ $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX))
ifeq ($(OPENJDK_TARGET_OS), windows)
ifneq ($$($1_MANIFEST), )
$$($1_MT) -nologo -manifest $$($1_MANIFEST) -identity:"$$($1_PROGRAM).exe, version=$$($1_MANIFEST_VERSION)" -outputresource:$$@;#1
--- a/nashorn/.hgtags Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/.hgtags Mon Sep 14 07:03:04 2015 +0000
@@ -313,3 +313,4 @@
33cecbc59f2ad78ac0934cbc3e014d346077e848 jdk9-b77
6f634e84387e97b2421d5e776e46935784156d1c jdk9-b78
9b3eca69b88b2d1bebce92d58280ae66fc0b6091 jdk9-b79
+61b401b23fc28208930977d46b690423911173c6 jdk9-b80
--- a/nashorn/make/project.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/make/project.properties Mon Sep 14 07:03:04 2015 +0000
@@ -302,7 +302,7 @@
-XX:+HeapDumpOnOutOfMemoryError
# turn on assertions for tests
-run.test.jvmargs.main=${run.test.jvmargs.common} -esa -ea
+run.test.jvmargs.main=${run.test.jvmargs.common} -esa -ea -da:java.lang.invoke.LambdaFormEditor
# Extra jvmargs that might be useful for debugging
# and performance improvements/monitoring
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Mon Sep 14 07:03:04 2015 +0000
@@ -107,7 +107,7 @@
private final AccessibleObject target;
private final MethodType type;
- public CallerSensitiveDynamicMethod(final AccessibleObject target) {
+ CallerSensitiveDynamicMethod(final AccessibleObject target) {
super(getName(target));
this.target = target;
this.type = getMethodType(target);
@@ -115,8 +115,9 @@
private static String getName(final AccessibleObject target) {
final Member m = (Member)target;
- return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(),
- m.getName()));
+ final boolean constructor = m instanceof Constructor;
+ return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() :
+ getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor);
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Mon Sep 14 07:03:04 2015 +0000
@@ -86,7 +86,9 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.text.Collator;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -242,6 +244,35 @@
return methods.getFirst().isConstructor();
}
+ @Override
+ public String toString() {
+ // First gather the names and sort them. This makes it consistent and easier to read.
+ final List<String> names = new ArrayList<>(methods.size());
+ int len = 0;
+ for (final SingleDynamicMethod m: methods) {
+ final String name = m.getName();
+ len += name.length();
+ names.add(name);
+ }
+ // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean".
+ final Collator collator = Collator.getInstance();
+ collator.setStrength(Collator.SECONDARY);
+ Collections.sort(names, collator);
+
+ final String className = getClass().getName();
+ // Class name length + length of signatures + 2 chars/per signature for indentation and newline +
+ // 3 for brackets and initial newline
+ final int totalLength = className.length() + len + 2 * names.size() + 3;
+ final StringBuilder b = new StringBuilder(totalLength);
+ b.append('[').append(className).append('\n');
+ for(final String name: names) {
+ b.append(' ').append(name).append('\n');
+ }
+ b.append(']');
+ assert b.length() == totalLength;
+ return b.toString();
+ };
+
ClassLoader getClassLoader() {
return classLoader;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Mon Sep 14 07:03:04 2015 +0000
@@ -122,13 +122,13 @@
* @param constructor does this represent a constructor?
*/
SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
- super(getName(target, clazz, name));
+ super(getName(target, clazz, name, constructor));
this.target = target;
this.constructor = constructor;
}
- private static String getName(final MethodHandle target, final Class<?> clazz, final String name) {
- return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name));
+ private static String getName(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
+ return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor);
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java Mon Sep 14 07:03:04 2015 +0000
@@ -143,14 +143,18 @@
return getMethodType().parameterList().equals(method.getMethodType().parameterList());
}
- static String getMethodNameWithSignature(final MethodType type, final String methodName) {
+ static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) {
final String typeStr = type.toString();
final int retTypeIndex = typeStr.lastIndexOf(')') + 1;
int secondParamIndex = typeStr.indexOf(',') + 1;
if(secondParamIndex == 0) {
secondParamIndex = retTypeIndex - 1;
}
- return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex);
+ final StringBuilder b = new StringBuilder();
+ if (withReturnType) {
+ b.append(typeStr, retTypeIndex, typeStr.length()).append(' ');
+ }
+ return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString();
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java Mon Sep 14 07:03:04 2015 +0000
@@ -51,6 +51,8 @@
private String fileName;
// script line number
private int line;
+ // are the line and fileName unknown?
+ private boolean lineAndFileNameUnknown;
// script column number
private int column;
// underlying ECMA error object - lazily initialized
@@ -92,27 +94,10 @@
*/
protected NashornException(final String msg, final Throwable cause) {
super(msg, cause == null ? null : cause);
- // This is not so pretty - but it gets the job done. Note that the stack
- // trace has been already filled by "fillInStackTrace" call from
- // Throwable
- // constructor and so we don't pay additional cost for it.
-
// Hard luck - no column number info
this.column = -1;
-
- // Find the first JavaScript frame by walking and set file, line from it
- // Usually, we should be able to find it in just few frames depth.
- for (final StackTraceElement ste : getStackTrace()) {
- if (ECMAErrors.isScriptFrame(ste)) {
- // Whatever here is compiled from JavaScript code
- this.fileName = ste.getFileName();
- this.line = ste.getLineNumber();
- return;
- }
- }
-
- this.fileName = null;
- this.line = 0;
+ // We can retrieve the line number and file name from the stack trace if needed
+ this.lineAndFileNameUnknown = true;
}
/**
@@ -121,6 +106,7 @@
* @return the file name
*/
public final String getFileName() {
+ ensureLineAndFileName();
return fileName;
}
@@ -131,6 +117,7 @@
*/
public final void setFileName(final String fileName) {
this.fileName = fileName;
+ lineAndFileNameUnknown = false;
}
/**
@@ -139,6 +126,7 @@
* @return the line number
*/
public final int getLineNumber() {
+ ensureLineAndFileName();
return line;
}
@@ -148,6 +136,7 @@
* @param line the line number
*/
public final void setLineNumber(final int line) {
+ lineAndFileNameUnknown = false;
this.line = line;
}
@@ -274,4 +263,19 @@
public void setEcmaError(final Object ecmaError) {
this.ecmaError = ecmaError;
}
+
+ private void ensureLineAndFileName() {
+ if (lineAndFileNameUnknown) {
+ for (final StackTraceElement ste : getStackTrace()) {
+ if (ECMAErrors.isScriptFrame(ste)) {
+ // Whatever here is compiled from JavaScript code
+ fileName = ste.getFileName();
+ line = ste.getLineNumber();
+ return;
+ }
+ }
+
+ lineAndFileNameUnknown = false;
+ }
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java Mon Sep 14 07:03:04 2015 +0000
@@ -283,17 +283,13 @@
start++;
}
- start++; //we always uses this
+ start++; // we always use this
- final List<IdentNode> params = functionNode.getParameters();
+ assert functionNode.getNumOfParams() == 0 : "apply2call on function with named paramaters!";
final List<IdentNode> newParams = new ArrayList<>();
- final long to = Math.max(params.size(), actualCallSiteType.parameterCount() - start);
+ final long to = actualCallSiteType.parameterCount() - start;
for (int i = 0; i < to; i++) {
- if (i >= params.size()) {
- newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i)));
- } else {
- newParams.add(params.get(i));
- }
+ newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i)));
}
callSiteTypes.push(actualCallSiteType);
@@ -316,6 +312,10 @@
return false;
}
+ if (functionNode.getNumOfParams() != 0) {
+ return false;
+ }
+
if (functionNode.hasEval()) {
return false;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Mon Sep 14 07:03:04 2015 +0000
@@ -149,12 +149,14 @@
private final Deque<Set<String>> thisProperties = new ArrayDeque<>();
private final Map<String, Symbol> globalSymbols = new HashMap<>(); //reuse the same global symbol
private final Compiler compiler;
+ private final boolean isOnDemand;
public AssignSymbols(final Compiler compiler) {
super(new LexicalContext());
this.compiler = compiler;
this.log = initLogger(compiler.getContext());
this.debug = log.isEnabled();
+ this.isOnDemand = compiler.isOnDemandCompilation();
}
@Override
@@ -390,7 +392,7 @@
// Create and add to appropriate block.
symbol = createSymbol(name, flags);
- symbolBlock.putSymbol(lc, symbol);
+ symbolBlock.putSymbol(symbol);
if ((flags & IS_SCOPE) == 0) {
// Initial assumption; symbol can lose its slot later
@@ -440,7 +442,7 @@
start(block);
if (lc.isFunctionBody()) {
- block.clearSymbols();
+ assert !block.hasSymbols();
final FunctionNode fn = lc.getCurrentFunction();
if (isUnparsedFunction(fn)) {
// It's a skipped nested function. Just mark the symbols being used by it as being in use.
@@ -459,7 +461,7 @@
}
private boolean isUnparsedFunction(final FunctionNode fn) {
- return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction();
+ return isOnDemand && fn != lc.getOutermostFunction();
}
@Override
@@ -747,28 +749,6 @@
}
}
- @Override
- public Node leaveBlock(final Block block) {
- // It's not necessary to guard the marking of symbols as locals with this "if" condition for
- // correctness, it's just an optimization -- runtime type calculation is not used when the compilation
- // is not an on-demand optimistic compilation, so we can skip locals marking then.
- if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) {
- // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand
- // compilation, and we're skipping parsing the function bodies for nested functions, this
- // basically only means their parameters. It'd be enough to mistakenly declare to be a local a
- // symbol in the outer function named the same as one of the parameters, though.
- if (lc.getFunction(block) == lc.getOutermostFunction()) {
- for (final Symbol symbol: block.getSymbols()) {
- if (!symbol.isScope()) {
- assert symbol.isVar() || symbol.isParam();
- compiler.declareLocalSymbol(symbol.getName());
- }
- }
- }
- }
- return block;
- }
-
private Node leaveDELETE(final UnaryNode unaryNode) {
final FunctionNode currentFunctionNode = lc.getCurrentFunction();
final boolean strictMode = currentFunctionNode.isStrict();
@@ -786,9 +766,9 @@
if (symbol.isThis()) {
// Can't delete "this", ignore and return true
- return LiteralNode.newInstance(unaryNode, true).accept(this);
+ return LiteralNode.newInstance(unaryNode, true);
}
- final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this);
+ final Expression literalNode = LiteralNode.newInstance(unaryNode, name);
final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel())));
if (!failDelete) {
@@ -799,7 +779,7 @@
if (failDelete) {
request = Request.FAIL_DELETE;
- } else if (symbol.isGlobal() && !symbol.isFunctionDeclaration()) {
+ } else if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) {
request = Request.SLOW_DELETE;
}
} else if (rhs instanceof AccessNode) {
@@ -807,7 +787,7 @@
final String property = ((AccessNode)rhs).getProperty();
args.add(base);
- args.add((Expression)LiteralNode.newInstance(unaryNode, property).accept(this));
+ args.add(LiteralNode.newInstance(unaryNode, property));
args.add(strictFlagNode);
} else if (rhs instanceof IndexNode) {
@@ -820,15 +800,15 @@
args.add(strictFlagNode);
} else {
- return LiteralNode.newInstance(unaryNode, true).accept(this);
+ return LiteralNode.newInstance(unaryNode, true);
}
- return new RuntimeNode(unaryNode, request, args).accept(this);
+ return new RuntimeNode(unaryNode, request, args);
}
@Override
public Node leaveForNode(final ForNode forNode) {
if (forNode.isForIn()) {
- forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73
+ return forNode.setIterator(lc, newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73
}
return end(forNode);
@@ -904,19 +884,18 @@
public Node leaveSwitchNode(final SwitchNode switchNode) {
// We only need a symbol for the tag if it's not an integer switch node
if(!switchNode.isUniqueInteger()) {
- switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX));
+ return switchNode.setTag(lc, newObjectInternal(SWITCH_TAG_PREFIX));
}
return switchNode;
}
@Override
public Node leaveTryNode(final TryNode tryNode) {
- tryNode.setException(exceptionSymbol());
assert tryNode.getFinallyBody() == null;
end(tryNode);
- return tryNode;
+ return tryNode.setException(lc, exceptionSymbol());
}
private Node leaveTYPEOF(final UnaryNode unaryNode) {
@@ -925,13 +904,13 @@
final List<Expression> args = new ArrayList<>();
if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) {
args.add(compilerConstantIdentifier(SCOPE));
- args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null
+ args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName())); //null
} else {
args.add(rhs);
- args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
+ args.add(LiteralNode.newInstance(unaryNode)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
}
- final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this);
+ final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args);
end(unaryNode);
@@ -939,7 +918,7 @@
}
private FunctionNode markProgramBlock(final FunctionNode functionNode) {
- if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) {
+ if (isOnDemand || !functionNode.isProgram()) {
return functionNode;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2010, 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. 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.internal.codegen;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.util.Collections;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.Statement;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.runtime.options.Options;
-
-/**
- * This static utility class performs serialization of FunctionNode ASTs to a byte array.
- * The format is a standard Java serialization stream, deflated.
- */
-final class AstSerializer {
- // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed
- // and size.
- private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
- static byte[] serialize(final FunctionNode fn) {
- final ByteArrayOutputStream out = new ByteArrayOutputStream();
- final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
- try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
- oout.writeObject(removeInnerFunctionBodies(fn));
- } catch (final IOException e) {
- throw new AssertionError("Unexpected exception serializing function", e);
- } finally {
- deflater.end();
- }
- return out.toByteArray();
- }
-
- private static FunctionNode removeInnerFunctionBodies(final FunctionNode fn) {
- return (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- @Override
- public Node leaveBlock(final Block block) {
- if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) {
- return block.setStatements(lc, Collections.<Statement>emptyList());
- }
- return super.leaveBlock(block);
- }
- });
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CacheAst.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+
+class CacheAst extends NodeVisitor<LexicalContext> {
+ private final Deque<RecompilableScriptFunctionData> dataStack = new ArrayDeque<>();
+
+ private final Compiler compiler;
+
+ CacheAst(final Compiler compiler) {
+ super(new LexicalContext());
+ this.compiler = compiler;
+ assert !compiler.isOnDemandCompilation();
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ final int id = functionNode.getId();
+ // It isn't necessary to keep a stack of RecompilableScriptFunctionData, but then we'd need to do a
+ // potentially transitive lookup with compiler.getScriptFunctionData(id) for deeper functions; this way
+ // we keep it constant time.
+ dataStack.push(dataStack.isEmpty() ? compiler.getScriptFunctionData(id) : dataStack.peek().getScriptFunctionData(id));
+ return true;
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ final RecompilableScriptFunctionData data = dataStack.pop();
+ if (functionNode.isSplit()) {
+ // NOTE: cache only split function ASTs from eager pass. Caching non-split functions would require
+ // some additional work, namely creating the concept of "uncacheable" function and reworking
+ // ApplySpecialization to ensure that functions undergoing apply-to-call transformations are not
+ // cacheable as well as recomputing Symbol.useCount when caching the eagerly parsed AST.
+ // Recomputing Symbol.useCount would be needed so it will only reflect uses from within the
+ // function being cached (and not reflect uses from its own nested functions or functions it is
+ // nested in). This is consistent with the count an on-demand recompilation of the function would
+ // produce. This is important as the decision to emit shared scope calls is based on this count,
+ // and if it is not matched between a previous version of the code and its deoptimizing rest-of
+ // compilation, it can result in rest-of not emitting a shared scope call where a previous version
+ // of the code (compiled from a cached eager pre-pass seeing higher (global) useCount) would emit
+ // it, causing a mismatch in stack shapes between previous code and its rest-of.
+ data.setCachedAst(functionNode);
+ }
+
+ if (!dataStack.isEmpty() && ((dataStack.peek().getFunctionFlags() & FunctionNode.IS_SPLIT) != 0)) {
+ // Return a function node with no body so that caching outer functions doesn't hold on to nested
+ // functions' bodies. Note we're doing this only for functions directly nested inside split
+ // functions, since we're only caching the split ones. It is not necessary to limit body removal
+ // to just these functions, but it's a cheap way to prevent unnecessary AST mutations.
+ return functionNode.setBody(lc, functionNode.getBody().setStatements(null, Collections.<Statement>emptyList()));
+ }
+ return functionNode;
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java Mon Sep 14 07:03:04 2015 +0000
@@ -48,11 +48,13 @@
import java.util.Set;
import jdk.nashorn.internal.AssertsEnabled;
import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
+import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -189,7 +191,7 @@
}
},
- SERIALIZE_SPLIT_PHASE(
+ CACHE_AST(
EnumSet.of(
INITIALIZED,
PARSED,
@@ -199,20 +201,21 @@
SPLIT)) {
@Override
FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
- return transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
- @Override
- public boolean enterFunctionNode(final FunctionNode functionNode) {
- if (functionNode.isSplit()) {
- compiler.serializeAst(functionNode);
- }
- return true;
- }
- });
+ if (!compiler.isOnDemandCompilation()) {
+ // Only do this on initial preprocessing of the source code. For on-demand compilations from
+ // source, FindScopeDepths#leaveFunctionNode() calls data.setCachedAst() for the sole function
+ // being compiled.
+ transformFunction(fn, new CacheAst(compiler));
+ }
+ // NOTE: we're returning the original fn as we have destructively modified the cached functions by
+ // removing their bodies. This step is associating FunctionNode objects with
+ // RecompilableScriptFunctionData; it's not really modifying the AST.
+ return fn;
}
@Override
public String toString() {
- return "'Serialize Split Functions'";
+ return "'Cache ASTs'";
}
},
@@ -255,6 +258,51 @@
}
},
+ DECLARE_LOCAL_SYMBOLS_TO_COMPILER(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT,
+ SYMBOLS_ASSIGNED,
+ SCOPE_DEPTHS_COMPUTED)) {
+ @Override
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ // It's not necessary to guard the marking of symbols as locals with this "if" condition for
+ // correctness, it's just an optimization -- runtime type calculation is not used when the compilation
+ // is not an on-demand optimistic compilation, so we can skip locals marking then.
+ if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) {
+ fn.getBody().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand
+ // compilation, and we're skipping parsing the function bodies for nested functions, this
+ // basically only means their parameters. It'd be enough to mistakenly declare to be a local a
+ // symbol in the outer function named the same as one of the parameters, though.
+ return false;
+ };
+ @Override
+ public boolean enterBlock(final Block block) {
+ for (final Symbol symbol: block.getSymbols()) {
+ if (!symbol.isScope()) {
+ compiler.declareLocalSymbol(symbol.getName());
+ }
+ }
+ return true;
+ };
+ });
+ }
+ return fn;
+ }
+
+ @Override
+ public String toString() {
+ return "'Local Symbols Declaration'";
+ }
+ },
+
OPTIMISTIC_TYPE_ASSIGNMENT_PHASE(
EnumSet.of(
INITIALIZED,
@@ -382,7 +430,7 @@
}
},
- REINITIALIZE_SERIALIZED(
+ REINITIALIZE_CACHED(
EnumSet.of(
INITIALIZED,
PARSED,
@@ -430,7 +478,7 @@
@Override
public String toString() {
- return "'Deserialize'";
+ return "'Reinitialize cached'";
}
},
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Mon Sep 14 07:03:04 2015 +0000
@@ -160,42 +160,41 @@
*/
private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32;
- private final Map<Integer, byte[]> serializedAsts = new HashMap<>();
-
/**
* Compilation phases that a compilation goes through
*/
public static class CompilationPhases implements Iterable<CompilationPhase> {
/**
- * Singleton that describes compilation up to the phase where a function can be serialized.
+ * Singleton that describes compilation up to the phase where a function can be cached.
*/
- private final static CompilationPhases COMPILE_UPTO_SERIALIZABLE = new CompilationPhases(
+ private final static CompilationPhases COMPILE_UPTO_CACHED = new CompilationPhases(
"Common initial phases",
CompilationPhase.CONSTANT_FOLDING_PHASE,
CompilationPhase.LOWERING_PHASE,
CompilationPhase.TRANSFORM_BUILTINS_PHASE,
CompilationPhase.SPLITTING_PHASE,
CompilationPhase.PROGRAM_POINT_PHASE,
- CompilationPhase.SERIALIZE_SPLIT_PHASE
+ CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
+ CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
+ CompilationPhase.CACHE_AST
);
- private final static CompilationPhases COMPILE_SERIALIZABLE_UPTO_BYTECODE = new CompilationPhases(
+ private final static CompilationPhases COMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases(
"After common phases, before bytecode generator",
- CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
- CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
+ CompilationPhase.DECLARE_LOCAL_SYMBOLS_TO_COMPILER,
CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE,
CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE
);
/**
- * Singleton that describes additional steps to be taken after deserializing, all the way up to (but not
- * including) generating and installing code.
+ * Singleton that describes additional steps to be taken after retrieving a cached function, all the
+ * way up to (but not including) generating and installing code.
*/
- public final static CompilationPhases RECOMPILE_SERIALIZED_UPTO_BYTECODE = new CompilationPhases(
- "Recompile serialized function up to bytecode",
- CompilationPhase.REINITIALIZE_SERIALIZED,
- COMPILE_SERIALIZABLE_UPTO_BYTECODE
+ public final static CompilationPhases RECOMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases(
+ "Recompile cached function up to bytecode",
+ CompilationPhase.REINITIALIZE_CACHED,
+ COMPILE_CACHED_UPTO_BYTECODE
);
/**
@@ -211,8 +210,8 @@
/** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */
public final static CompilationPhases COMPILE_UPTO_BYTECODE = new CompilationPhases(
"Compile upto bytecode",
- COMPILE_UPTO_SERIALIZABLE,
- COMPILE_SERIALIZABLE_UPTO_BYTECODE);
+ COMPILE_UPTO_CACHED,
+ COMPILE_CACHED_UPTO_BYTECODE);
/** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */
public final static CompilationPhases COMPILE_ALL_NO_INSTALL = new CompilationPhases(
@@ -227,9 +226,9 @@
GENERATE_BYTECODE_AND_INSTALL);
/** Singleton that describes a full compilation - this includes code installation - from serialized state*/
- public final static CompilationPhases COMPILE_ALL_SERIALIZED = new CompilationPhases(
+ public final static CompilationPhases COMPILE_ALL_CACHED = new CompilationPhases(
"Eager compilation from serializaed state",
- RECOMPILE_SERIALIZED_UPTO_BYTECODE,
+ RECOMPILE_CACHED_UPTO_BYTECODE,
GENERATE_BYTECODE_AND_INSTALL);
/**
@@ -248,9 +247,9 @@
GENERATE_BYTECODE_AND_INSTALL_RESTOF);
/** Compile from serialized for a rest of method */
- public final static CompilationPhases COMPILE_SERIALIZED_RESTOF = new CompilationPhases(
+ public final static CompilationPhases COMPILE_CACHED_RESTOF = new CompilationPhases(
"Compile serialized, rest of",
- RECOMPILE_SERIALIZED_UPTO_BYTECODE,
+ RECOMPILE_CACHED_UPTO_BYTECODE,
GENERATE_BYTECODE_AND_INSTALL_RESTOF);
private final List<CompilationPhase> phases;
@@ -313,7 +312,7 @@
}
boolean isRestOfCompilation() {
- return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_SERIALIZED_RESTOF;
+ return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_CACHED_RESTOF;
}
String getDesc() {
@@ -766,14 +765,6 @@
compileUnits.addAll(newUnits);
}
- void serializeAst(final FunctionNode fn) {
- serializedAsts.put(fn.getId(), AstSerializer.serialize(fn));
- }
-
- byte[] removeSerializedAst(final int fnId) {
- return serializedAsts.remove(fnId);
- }
-
CompileUnit findUnit(final long weight) {
for (final CompileUnit unit : compileUnits) {
if (unit.canHold(weight)) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java Mon Sep 14 07:03:04 2015 +0000
@@ -188,6 +188,9 @@
log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope.");
newFunctionNode = newFunctionNode.setInDynamicContext(lc);
}
+ if (newFunctionNode == lc.getOutermostFunction() && !newFunctionNode.hasApplyToCallSpecialization()) {
+ data.setCachedAst(newFunctionNode);
+ }
return newFunctionNode;
}
@@ -208,8 +211,7 @@
ObjectClassGenerator.createAllocationStrategy(newFunctionNode.getThisProperties(), compiler.getContext().useDualFields()),
nestedFunctions,
externalSymbolDepths.get(fnId),
- internalSymbols.get(fnId),
- compiler.removeSerializedAst(fnId));
+ internalSymbols.get(fnId));
if (lc.getOutermostFunction() != newFunctionNode) {
final FunctionNode parentFn = lc.getParentFunction(newFunctionNode);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java Mon Sep 14 07:03:04 2015 +0000
@@ -497,7 +497,7 @@
private transient Label.Stack stack;
/** ASM representation of this label */
- private jdk.internal.org.objectweb.asm.Label label;
+ private transient jdk.internal.org.objectweb.asm.Label label;
/** Id for debugging purposes, remove if footprint becomes unmanageable */
private final int id;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeMap.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeMap.java Mon Sep 14 07:03:04 2015 +0000
@@ -27,21 +27,18 @@
import java.lang.invoke.MethodType;
import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
import java.util.NoSuchElementException;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.runtime.ScriptFunction;
/**
- * A data structure that maps one or several function nodes (by their unique id:s, not by
- * the FunctionNode object itself, due to copy on write changing it several times through
- * code generation.
+ * A tuple containing function id, parameter types, return type and needsCallee flag.
*/
-public class TypeMap {
- private final Map<Integer, Type[]> paramTypeMap = new HashMap<>();
- private final Map<Integer, Type> returnTypeMap = new HashMap<>();
+public final class TypeMap {
+ private final int functionNodeId;
+ private final Type[] paramTypes;
+ private final Type returnType;
private final boolean needsCallee;
/**
@@ -56,9 +53,10 @@
for (final Class<?> p : type.parameterArray()) {
types[pos++] = Type.typeFor(p);
}
- paramTypeMap.put(functionNodeId, types);
- returnTypeMap.put(functionNodeId, Type.typeFor(type.returnType()));
+ this.functionNodeId = functionNodeId;
+ this.paramTypes = types;
+ this.returnType = Type.typeFor(type.returnType());
this.needsCallee = needsCallee;
}
@@ -69,20 +67,14 @@
* @throws NoSuchElementException if the type map has no mapping for the requested function
*/
public Type[] getParameterTypes(final int functionNodeId) {
- final Type[] paramTypes = paramTypeMap.get(functionNodeId);
- if (paramTypes == null) {
- throw new NoSuchElementException(Integer.toString(functionNodeId));
- }
+ assert this.functionNodeId == functionNodeId;
return paramTypes.clone();
}
MethodType getCallSiteType(final FunctionNode functionNode) {
- final Type[] types = paramTypeMap.get(functionNode.getId());
- if (types == null) {
- return null;
- }
-
- MethodType mt = MethodType.methodType(returnTypeMap.get(functionNode.getId()).getTypeClass());
+ assert this.functionNodeId == functionNode.getId();
+ final Type[] types = paramTypes;
+ MethodType mt = MethodType.methodType(returnType.getTypeClass());
if (needsCallee) {
mt = mt.appendParameterTypes(ScriptFunction.class);
}
@@ -116,7 +108,8 @@
* @return parameter type for this callsite if known
*/
Type get(final FunctionNode functionNode, final int pos) {
- final Type[] types = paramTypeMap.get(functionNode.getId());
+ assert this.functionNodeId == functionNode.getId();
+ final Type[] types = paramTypes;
assert types == null || pos < types.length : "fn = " + functionNode.getId() + " " + "types=" + Arrays.toString(types) + " || pos=" + pos + " >= length=" + types.length + " in " + this;
if (types != null && pos < types.length) {
return types[pos];
@@ -124,13 +117,6 @@
return null;
}
- boolean has(final FunctionNode functionNode) {
- final int id = functionNode.getId();
- final Type[] paramTypes = paramTypeMap.get(id);
- assert (paramTypes == null) == (returnTypeMap.get(id) == null) : "inconsistent param and return types in param map";
- return paramTypes != null;
- }
-
@Override
public String toString() {
return toString("");
@@ -139,27 +125,16 @@
String toString(final String prefix) {
final StringBuilder sb = new StringBuilder();
- if (paramTypeMap.isEmpty()) {
- sb.append(prefix).append("\t<empty>");
- return sb.toString();
- }
-
- for (final Map.Entry<Integer, Type[]> entry : paramTypeMap.entrySet()) {
- final int id = entry.getKey();
- sb.append(prefix).append('\t');
- sb.append("function ").append(id).append('\n');
- sb.append(prefix).append("\t\tparamTypes=");
- if (entry.getValue() == null) {
- sb.append("[]");
- } else {
- sb.append(Arrays.toString(entry.getValue()));
- }
- sb.append('\n');
- sb.append(prefix).append("\t\treturnType=");
- final Type ret = returnTypeMap.get(id);
- sb.append(ret == null ? "N/A" : ret);
- sb.append('\n');
- }
+ final int id = functionNodeId;
+ sb.append(prefix).append('\t');
+ sb.append("function ").append(id).append('\n');
+ sb.append(prefix).append("\t\tparamTypes=");
+ sb.append(Arrays.toString(paramTypes));
+ sb.append('\n');
+ sb.append(prefix).append("\t\treturnType=");
+ final Type ret = returnType;
+ sb.append(ret == null ? "N/A" : ret);
+ sb.append('\n');
return sb.toString();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java Mon Sep 14 07:03:04 2015 +0000
@@ -159,11 +159,42 @@
}
/**
- * Clear the symbols in the block.
- * TODO: make this immutable.
+ * Returns true if this block defines any symbols.
+ * @return true if this block defines any symbols.
+ */
+ public boolean hasSymbols() {
+ return !symbols.isEmpty();
+ }
+
+ /**
+ * Replaces symbols defined in this block with different symbols. Used to ensure symbol tables are
+ * immutable upon construction and have copy-on-write semantics. Note that this method only replaces the
+ * symbols in the symbol table, it does not act on any contained AST nodes that might reference the symbols.
+ * Those should be updated separately as this method is meant to be used as part of such an update pass.
+ * @param lc the current lexical context
+ * @param replacements the map of symbol replacements
+ * @return a new block with replaced symbols, or this block if none of the replacements modified the symbol
+ * table.
*/
- public void clearSymbols() {
- symbols.clear();
+ public Block replaceSymbols(final LexicalContext lc, final Map<Symbol, Symbol> replacements) {
+ if (symbols.isEmpty()) {
+ return this;
+ }
+ final LinkedHashMap<String, Symbol> newSymbols = new LinkedHashMap<>(symbols);
+ for (final Map.Entry<String, Symbol> entry: newSymbols.entrySet()) {
+ final Symbol newSymbol = replacements.get(entry.getValue());
+ assert newSymbol != null : "Missing replacement for " + entry.getKey();
+ entry.setValue(newSymbol);
+ }
+ return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, newSymbols, conversion));
+ }
+
+ /**
+ * Returns a copy of this block with a shallow copy of the symbol table.
+ * @return a copy of this block with a shallow copy of the symbol table.
+ */
+ public Block copyWithNewSymbols() {
+ return new Block(this, finish, statements, flags, new LinkedHashMap<>(symbols), conversion);
}
@Override
@@ -191,7 +222,7 @@
* @return symbol iterator
*/
public List<Symbol> getSymbols() {
- return Collections.unmodifiableList(new ArrayList<>(symbols.values()));
+ return symbols.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(new ArrayList<>(symbols.values()));
}
/**
@@ -355,10 +386,9 @@
/**
* Add or overwrite an existing symbol in the block
*
- * @param lc get lexical context
* @param symbol symbol
*/
- public void putSymbol(final LexicalContext lc, final Symbol symbol) {
+ public void putSymbol(final Symbol symbol) {
symbols.put(symbol.getName(), symbol);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java Mon Sep 14 07:03:04 2015 +0000
@@ -43,7 +43,7 @@
private final JoinPredecessorExpression modify;
/** Iterator symbol. */
- private Symbol iterator;
+ private final Symbol iterator;
/** Is this a normal for in loop? */
public static final int IS_FOR_IN = 1 << 0;
@@ -86,23 +86,23 @@
this.flags = flags;
this.init = init;
this.modify = modify;
+ this.iterator = null;
}
private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test,
- final Block body, final JoinPredecessorExpression modify, final int flags, final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
+ final Block body, final JoinPredecessorExpression modify, final int flags,
+ final boolean controlFlowEscapes, final LocalVariableConversion conversion, final Symbol iterator) {
super(forNode, test, body, controlFlowEscapes, conversion);
this.init = init;
this.modify = modify;
this.flags = flags;
- // Even if the for node gets cloned in try/finally, the symbol can be shared as only one branch of the finally
- // is executed.
- this.iterator = forNode.iterator;
+ this.iterator = iterator;
}
@Override
public Node ensureUniqueLabels(final LexicalContext lc) {
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
}
@Override
@@ -175,7 +175,7 @@
if (this.init == init) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
}
/**
@@ -204,10 +204,15 @@
/**
* Assign an iterator symbol to this ForNode. Used for for in and for each constructs
+ * @param lc the current lexical context
* @param iterator the iterator symbol
+ * @return a ForNode with the iterator set
*/
- public void setIterator(final Symbol iterator) {
- this.iterator = iterator;
+ public ForNode setIterator(final LexicalContext lc, final Symbol iterator) {
+ if (this.iterator == iterator) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
}
/**
@@ -228,7 +233,7 @@
if (this.modify == modify) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
}
@Override
@@ -236,7 +241,7 @@
if (this.test == test) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
}
@Override
@@ -249,7 +254,7 @@
if (this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
}
@Override
@@ -257,12 +262,12 @@
if (this.controlFlowEscapes == controlFlowEscapes) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
}
@Override
JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java Mon Sep 14 07:03:04 2015 +0000
@@ -264,6 +264,11 @@
*/
public static final int NEEDS_CALLEE = 1 << 26;
+ /**
+ * Is the function node cached?
+ */
+ public static final int IS_CACHED = 1 << 27;
+
/** extension callsite flags mask */
public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
@@ -353,7 +358,7 @@
final List<IdentNode> parameters,
final int thisProperties,
final Class<?> rootClass,
- final Source source, Namespace namespace) {
+ final Source source, final Namespace namespace) {
super(functionNode);
this.endParserState = endParserState;
@@ -757,7 +762,7 @@
*/
public boolean needsCallee() {
// NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
- return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
+ return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasApplyToCallSpecialization();
}
/**
@@ -774,7 +779,7 @@
* Return true if function contains an apply to call transform
* @return true if this function has transformed apply to call
*/
- public boolean hasOptimisticApplyToCall() {
+ public boolean hasApplyToCallSpecialization() {
return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
}
@@ -1026,6 +1031,14 @@
}
/**
+ * Return the number of parameters to this function
+ * @return the number of parameters
+ */
+ public int getNumOfParams() {
+ return parameters.size();
+ }
+
+ /**
* Returns the identifier for a named parameter at the specified position in this function's parameter list.
* @param index the parameter's position.
* @return the identifier for the requested named parameter.
@@ -1162,6 +1175,24 @@
}
/**
+ * Returns true if this function node has been cached.
+ * @return true if this function node has been cached.
+ */
+ public boolean isCached() {
+ return getFlag(IS_CACHED);
+ }
+
+ /**
+ * Mark this function node as having been cached.
+ * @param lc the current lexical context
+ * @return a function node equivalent to this one, with the flag set.
+ */
+ public FunctionNode setCached(final LexicalContext lc) {
+ return setFlag(lc, IS_CACHED);
+ }
+
+
+ /**
* Get the compile unit used to compile this function
* @see Compiler
* @return the compile unit
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SwitchNode.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SwitchNode.java Mon Sep 14 07:03:04 2015 +0000
@@ -53,7 +53,7 @@
private final boolean uniqueInteger;
/** Tag symbol. */
- private Symbol tag;
+ private final Symbol tag;
/**
* Constructor
@@ -71,15 +71,16 @@
this.cases = cases;
this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase);
this.uniqueInteger = false;
+ this.tag = null;
}
private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases,
- final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger) {
+ final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger, final Symbol tag) {
super(switchNode, conversion);
this.expression = expression;
this.cases = cases;
this.defaultCaseIndex = defaultCaseIndex;
- this.tag = switchNode.getTag(); //TODO are symbols inherited as references?
+ this.tag = tag;
this.uniqueInteger = uniqueInteger;
}
@@ -89,7 +90,7 @@
for (final CaseNode caseNode : cases) {
newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody(), caseNode.getLocalVariableConversion()));
}
- return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger));
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger, tag));
}
@Override
@@ -157,7 +158,7 @@
if (this.cases == cases) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
}
/**
@@ -189,7 +190,7 @@
if (this.expression == expression) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
}
/**
@@ -204,10 +205,15 @@
/**
* Set the tag symbol for this switch. The tag symbol is where
* the switch expression result is stored
+ * @param lc lexical context
* @param tag a symbol
+ * @return a switch node with the symbol set
*/
- public void setTag(final Symbol tag) {
- this.tag = tag;
+ public SwitchNode setTag(final LexicalContext lc, final Symbol tag) {
+ if (this.tag == tag) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
}
/**
@@ -229,12 +235,12 @@
if(this.uniqueInteger == uniqueInteger) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
}
@Override
JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
- return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Symbol.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Symbol.java Mon Sep 14 07:03:04 2015 +0000
@@ -25,7 +25,10 @@
package jdk.nashorn.internal.ir;
+import java.io.IOException;
+import java.io.ObjectInputStream;
import java.io.PrintWriter;
+import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
@@ -47,7 +50,9 @@
* refer to their location.
*/
-public final class Symbol implements Comparable<Symbol> {
+public final class Symbol implements Comparable<Symbol>, Cloneable, Serializable {
+ private static final long serialVersionUID = 1L;
+
/** Is this Global */
public static final int IS_GLOBAL = 1;
/** Is this a variable */
@@ -94,10 +99,10 @@
/** First bytecode method local variable slot for storing the value(s) of this variable. -1 indicates the variable
* is not stored in local variable slots or it is not yet known. */
- private int firstSlot = -1;
+ private transient int firstSlot = -1;
/** Field number in scope or property; array index in varargs when not using arguments object. */
- private int fieldIndex = -1;
+ private transient int fieldIndex = -1;
/** Number of times this symbol is used in code */
private int useCount;
@@ -144,6 +149,15 @@
}
}
+ @Override
+ public Symbol clone() {
+ try {
+ return (Symbol)super.clone();
+ } catch (final CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
private static String align(final String string, final int max) {
final StringBuilder sb = new StringBuilder();
sb.append(string.substring(0, Math.min(string.length(), max)));
@@ -337,7 +351,7 @@
* Flag this symbol as scope as described in {@link Symbol#isScope()}
* @return the symbol
*/
- public Symbol setIsScope() {
+ public Symbol setIsScope() {
if (!isScope()) {
if(shouldTrace()) {
trace("SET IS SCOPE");
@@ -609,11 +623,11 @@
/**
* Increase the symbol's use count by one.
- * @return the symbol
*/
- public Symbol increaseUseCount() {
- useCount++;
- return this;
+ public void increaseUseCount() {
+ if (isScope()) { // Avoid dirtying a cache line; we only need the use count for scoped symbols
+ useCount++;
+ }
}
/**
@@ -669,4 +683,10 @@
new Throwable().printStackTrace(Context.getCurrentErr());
}
}
+
+ private void readObject(final ObjectInputStream in) throws ClassNotFoundException, IOException {
+ in.defaultReadObject();
+ firstSlot = -1;
+ fieldIndex = -1;
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java Mon Sep 14 07:03:04 2015 +0000
@@ -65,7 +65,7 @@
private final List<Block> inlinedFinallies;
/** Exception symbol. */
- private Symbol exception;
+ private final Symbol exception;
private final LocalVariableConversion conversion;
@@ -86,22 +86,23 @@
this.finallyBody = finallyBody;
this.conversion = null;
this.inlinedFinallies = Collections.emptyList();
+ this.exception = null;
}
- private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies) {
+ private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies, final Symbol exception) {
super(tryNode);
this.body = body;
this.catchBlocks = catchBlocks;
this.finallyBody = finallyBody;
this.conversion = conversion;
this.inlinedFinallies = inlinedFinallies;
- this.exception = tryNode.exception;
+ this.exception = exception;
}
@Override
public Node ensureUniqueLabels(final LexicalContext lc) {
//try nodes are never in lex context
- return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies);
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception);
}
@Override
@@ -160,7 +161,7 @@
if (this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
}
/**
@@ -197,7 +198,7 @@
if (this.catchBlocks == catchBlocks) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
}
/**
@@ -209,12 +210,15 @@
}
/**
* Set the exception symbol for this try block
+ * @param lc lexical context
* @param exception a symbol for the compiler to store the exception in
* @return new TryNode or same if unchanged
*/
- public TryNode setException(final Symbol exception) {
- this.exception = exception;
- return this;
+ public TryNode setException(final LexicalContext lc, final Symbol exception) {
+ if (this.exception == exception) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
}
/**
@@ -277,7 +281,7 @@
if (this.finallyBody == finallyBody) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
}
/**
@@ -293,7 +297,7 @@
return this;
}
assert checkInlinedFinallies(inlinedFinallies);
- return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
}
private static boolean checkInlinedFinallies(final List<Block> inlinedFinallies) {
@@ -314,7 +318,7 @@
if(this.conversion == conversion) {
return this;
}
- return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies);
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception);
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Mon Sep 14 07:03:04 2015 +0000
@@ -2419,7 +2419,7 @@
}
private void initScripting(final ScriptEnvironment scriptEnv) {
- Object value;
+ ScriptObject value;
value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
@@ -2428,11 +2428,13 @@
final String execName = ScriptingFunctions.EXEC_NAME;
value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
+ value.addOwnProperty(ScriptingFunctions.THROW_ON_ERROR_NAME, Attribute.NOT_ENUMERABLE, false);
+
addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
// Nashorn extension: global.echo (scripting-mode-only)
// alias for "print"
- value = get("print");
+ value = (ScriptObject)get("print");
addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
// Nashorn extension: global.$OPTIONS (scripting-mode-only)
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Mon Sep 14 07:03:04 2015 +0000
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.parser;
import static jdk.nashorn.internal.parser.TokenType.ADD;
+import static jdk.nashorn.internal.parser.TokenType.BINARY_NUMBER;
import static jdk.nashorn.internal.parser.TokenType.COMMENT;
import static jdk.nashorn.internal.parser.TokenType.DECIMAL;
import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
@@ -40,6 +41,7 @@
import static jdk.nashorn.internal.parser.TokenType.LBRACE;
import static jdk.nashorn.internal.parser.TokenType.LPAREN;
import static jdk.nashorn.internal.parser.TokenType.OCTAL;
+import static jdk.nashorn.internal.parser.TokenType.OCTAL_LEGACY;
import static jdk.nashorn.internal.parser.TokenType.RBRACE;
import static jdk.nashorn.internal.parser.TokenType.REGEX;
import static jdk.nashorn.internal.parser.TokenType.RPAREN;
@@ -47,6 +49,7 @@
import static jdk.nashorn.internal.parser.TokenType.XML;
import java.io.Serializable;
+
import jdk.nashorn.internal.runtime.ECMAErrors;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.JSErrorType;
@@ -75,6 +78,9 @@
/** True if here and edit strings are supported. */
private final boolean scripting;
+ /** True if parsing in ECMAScript 6 mode. */
+ private final boolean es6;
+
/** True if a nested scan. (scan to completion, no EOF.) */
private final boolean nested;
@@ -173,7 +179,7 @@
* @param stream the token stream to lex
*/
public Lexer(final Source source, final TokenStream stream) {
- this(source, stream, false);
+ this(source, stream, false, false);
}
/**
@@ -182,9 +188,10 @@
* @param source the source
* @param stream the token stream to lex
* @param scripting are we in scripting mode
+ * @param es6 are we in ECMAScript 6 mode
*/
- public Lexer(final Source source, final TokenStream stream, final boolean scripting) {
- this(source, 0, source.getLength(), stream, scripting, false);
+ public Lexer(final Source source, final TokenStream stream, final boolean scripting, final boolean es6) {
+ this(source, 0, source.getLength(), stream, scripting, es6, false);
}
/**
@@ -195,16 +202,18 @@
* @param len length of source segment to lex
* @param stream token stream to lex
* @param scripting are we in scripting mode
+ * @param es6 are we in ECMAScript 6 mode
* @param pauseOnFunctionBody if true, lexer will return from {@link #lexify()} when it encounters a
* function body. This is used with the feature where the parser is skipping nested function bodies to
* avoid reading ahead unnecessarily when we skip the function bodies.
*/
- public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean pauseOnFunctionBody) {
+ public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean es6, final boolean pauseOnFunctionBody) {
super(source.getContent(), 1, start, len);
this.source = source;
this.stream = stream;
this.scripting = scripting;
+ this.es6 = es6;
this.nested = false;
this.pendingLine = 1;
this.last = EOL;
@@ -218,6 +227,7 @@
source = lexer.source;
stream = lexer.stream;
scripting = lexer.scripting;
+ es6 = lexer.es6;
nested = true;
pendingLine = state.pendingLine;
@@ -1088,6 +1098,24 @@
}
type = HEXADECIMAL;
+ } else if (digit == 0 && es6 && (ch1 == 'o' || ch1 == 'O') && convertDigit(ch2, 8) != -1) {
+ // Skip over 0oN.
+ skip(3);
+ // Skip over remaining digits.
+ while (convertDigit(ch0, 8) != -1) {
+ skip(1);
+ }
+
+ type = OCTAL;
+ } else if (digit == 0 && es6 && (ch1 == 'b' || ch1 == 'B') && convertDigit(ch2, 2) != -1) {
+ // Skip over 0bN.
+ skip(3);
+ // Skip over remaining digits.
+ while (convertDigit(ch0, 2) != -1) {
+ skip(1);
+ }
+
+ type = BINARY_NUMBER;
} else {
// Check for possible octal constant.
boolean octal = digit == 0;
@@ -1105,7 +1133,7 @@
}
if (octal && position - start > 1) {
- type = OCTAL;
+ type = OCTAL_LEGACY;
} else if (ch0 == '.' || ch0 == 'E' || ch0 == 'e') {
// Must be a double.
if (ch0 == '.') {
@@ -1637,10 +1665,14 @@
switch (Token.descType(token)) {
case DECIMAL:
return Lexer.valueOf(source.getString(start, len), 10); // number
- case OCTAL:
- return Lexer.valueOf(source.getString(start, len), 8); // number
case HEXADECIMAL:
return Lexer.valueOf(source.getString(start + 2, len - 2), 16); // number
+ case OCTAL_LEGACY:
+ return Lexer.valueOf(source.getString(start, len), 8); // number
+ case OCTAL:
+ return Lexer.valueOf(source.getString(start + 2, len - 2), 8); // number
+ case BINARY_NUMBER:
+ return Lexer.valueOf(source.getString(start + 2, len - 2), 2); // number
case FLOATING:
final String str = source.getString(start, len);
final double value = Double.valueOf(str);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Mon Sep 14 07:03:04 2015 +0000
@@ -273,7 +273,7 @@
try {
stream = new TokenStream();
- lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, reparsedFunction != null);
+ lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
lexer.line = lexer.pendingLine = lineOffset + 1;
line = lineOffset;
@@ -309,7 +309,7 @@
public List<IdentNode> parseFormalParameterList() {
try {
stream = new TokenStream();
- lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
+ lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
// Set up first token (skips opening EOL.)
k = -1;
@@ -333,7 +333,7 @@
public FunctionNode parseFunctionBody() {
try {
stream = new TokenStream();
- lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
+ lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
final int functionLine = line;
// Set up first token (skips opening EOL.)
@@ -716,7 +716,7 @@
restoreBlock(body);
body.setFlag(Block.NEEDS_SCOPE);
- final Block programBody = new Block(functionToken, functionLine, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
+ final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
lc.pop(script);
script.setLastToken(token);
@@ -1216,11 +1216,10 @@
final long forToken = token;
final int forLine = line;
// start position of this for statement. This is used
- // for sort order for variables declared in the initialzer
+ // for sort order for variables declared in the initializer
// part of this 'for' statement (if any).
final int forStart = Token.descPosition(forToken);
// When ES6 for-let is enabled we create a container block to capture the LET.
- final int startLine = start;
final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
// Create FOR node, capturing FOR token.
@@ -1341,22 +1340,24 @@
body = getStatement();
} finally {
lc.pop(forNode);
- }
-
- if (vars != null) {
- for (final VarNode var : vars) {
- appendStatement(var);
+
+ if (vars != null) {
+ for (final VarNode var : vars) {
+ appendStatement(var);
+ }
+ }
+ if (body != null) {
+ appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
}
- }
- if (body != null) {
- appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
- }
- if (outer != null) {
- restoreBlock(outer);
- appendStatement(new BlockStatement(startLine, new Block(
- outer.getToken(),
- body.getFinish(),
- outer.getStatements())));
+ if (outer != null) {
+ restoreBlock(outer);
+ if (body != null) {
+ appendStatement(new BlockStatement(forLine, new Block(
+ outer.getToken(),
+ body.getFinish(),
+ outer.getStatements())));
+ }
+ }
}
}
@@ -1954,7 +1955,7 @@
}
detectSpecialProperty(ident);
return ident;
- case OCTAL:
+ case OCTAL_LEGACY:
if (isStrictMode) {
throw error(AbstractParser.message("strict.no.octal"), token);
}
@@ -1962,6 +1963,8 @@
case ESCSTRING:
case DECIMAL:
case HEXADECIMAL:
+ case OCTAL:
+ case BINARY_NUMBER:
case FLOATING:
case REGEX:
case XML:
@@ -2053,13 +2056,13 @@
// LBRACKET tested in caller.
next();
- // Prepare to accummulating elements.
+ // Prepare to accumulate elements.
final List<Expression> elements = new ArrayList<>();
// Track elisions.
boolean elision = true;
loop:
while (true) {
- switch (type) {
+ switch (type) {
case RBRACKET:
next();
@@ -2223,7 +2226,7 @@
switch (type) {
case IDENT:
return getIdent().setIsPropertyName();
- case OCTAL:
+ case OCTAL_LEGACY:
if (isStrictMode) {
throw error(AbstractParser.message("strict.no.octal"), token);
}
@@ -2231,6 +2234,8 @@
case ESCSTRING:
case DECIMAL:
case HEXADECIMAL:
+ case OCTAL:
+ case BINARY_NUMBER:
case FLOATING:
return getLiteral();
default:
@@ -2284,7 +2289,7 @@
}
}
- propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
+ propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
} else {
propertyName = propertyName();
}
@@ -2553,7 +2558,7 @@
final long callToken = token;
switch (type) {
- case LBRACKET:
+ case LBRACKET: {
next();
// Get array index.
@@ -2565,8 +2570,8 @@
lhs = new IndexNode(callToken, finish, lhs, index);
break;
-
- case PERIOD:
+ }
+ case PERIOD: {
if (lhs == null) {
throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
}
@@ -2579,7 +2584,7 @@
lhs = new AccessNode(callToken, finish, lhs, property.getName());
break;
-
+ }
default:
break loop;
}
@@ -3034,7 +3039,7 @@
assert parserState != null;
stream.reset();
- lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions);
+ lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
line = parserState.line;
linePosition = parserState.linePosition;
// Doesn't really matter, but it's safe to treat it as if there were a semicolon before
@@ -3063,8 +3068,8 @@
this.linePosition = linePosition;
}
- Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) {
- final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true);
+ Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
+ final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
return newLexer;
}
@@ -3107,15 +3112,6 @@
return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
}
- /*
- * parse LHS [a, b, ..., c].
- *
- * JavaScript 1.8.
- */
- //private Node destructureExpression() {
- // return null;
- //}
-
/**
* PostfixExpression :
* LeftHandSideExpression
@@ -3127,7 +3123,7 @@
* UnaryExpression :
* PostfixExpression
* delete UnaryExpression
- * Node UnaryExpression
+ * void UnaryExpression
* typeof UnaryExpression
* ++ UnaryExpression
* -- UnaryExpression
@@ -3333,7 +3329,6 @@
// This method is protected so that subclass can get details
// at expression start point!
- // TODO - Destructuring array.
// Include commas in expression parsing.
return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
}
@@ -3407,7 +3402,6 @@
// This method is protected so that subclass can get details
// at assignment expression start point!
- // TODO - Handle decompose.
// Exclude commas in expression parsing.
return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Mon Sep 14 07:03:04 2015 +0000
@@ -170,8 +170,10 @@
YIELD (FUTURESTRICT, "yield"),
DECIMAL (LITERAL, null),
+ HEXADECIMAL (LITERAL, null),
+ OCTAL_LEGACY (LITERAL, null),
OCTAL (LITERAL, null),
- HEXADECIMAL (LITERAL, null),
+ BINARY_NUMBER (LITERAL, null),
FLOATING (LITERAL, null),
STRING (LITERAL, null),
ESCSTRING (LITERAL, null),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstSerializer.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010, 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. 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.internal.runtime;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * This static utility class performs serialization of FunctionNode ASTs to a byte array.
+ * The format is a standard Java serialization stream, deflated.
+ */
+final class AstSerializer {
+ // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed
+ // and size.
+ private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
+ static byte[] serialize(final FunctionNode fn) {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
+ try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
+ oout.writeObject(fn);
+ } catch (final IOException e) {
+ throw new AssertionError("Unexpected exception serializing function", e);
+ } finally {
+ deflater.end();
+ }
+ return out.toByteArray();
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Mon Sep 14 07:03:04 2015 +0000
@@ -27,6 +27,7 @@
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -820,7 +821,7 @@
// isn't available, we'll use the old one bound into the call site.
final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo;
FunctionNode fn = effectiveOptInfo.reparse();
- final boolean serialized = effectiveOptInfo.isSerialized();
+ final boolean cached = fn.isCached();
final Compiler compiler = effectiveOptInfo.getCompiler(fn, ct, re); //set to non rest-of
if (!shouldRecompile) {
@@ -828,11 +829,11 @@
// recompiled a deoptimized version for an inner invocation.
// We still need to do the rest of from the beginning
logRecompile("Rest-of compilation [STANDALONE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
- return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
+ return restOfHandle(effectiveOptInfo, compiler.compile(fn, cached ? CompilationPhases.COMPILE_CACHED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
}
logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
- fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
+ fn = compiler.compile(fn, cached ? CompilationPhases.RECOMPILE_CACHED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
log.fine("Reusable IR generated");
// compile the rest of the function, and install it
@@ -956,10 +957,6 @@
FunctionNode reparse() {
return data.reparse();
}
-
- boolean isSerialized() {
- return data.isSerialized();
- }
}
@SuppressWarnings("unused")
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Mon Sep 14 07:03:04 2015 +0000
@@ -26,16 +26,24 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
@@ -45,8 +53,15 @@
import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
import jdk.nashorn.internal.codegen.TypeMap;
import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TryNode;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Parser;
@@ -55,6 +70,7 @@
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.Options;
/**
* This is a subclass that represents a script function that may be regenerated,
* for example with specialization based on call site types, or lazily generated.
@@ -66,6 +82,8 @@
/** Prefix used for all recompiled script classes */
public static final String RECOMPILATION_PREFIX = "Recompilation$";
+ private static final ExecutorService astSerializerExecutorService = createAstSerializerExecutorService();
+
/** Unique function node id for this function node */
private final int functionNodeId;
@@ -77,8 +95,12 @@
/** Source from which FunctionNode was parsed. */
private transient Source source;
- /** Serialized, compressed form of the AST. Used by split functions as they can't be reparsed from source. */
- private final byte[] serializedAst;
+ /**
+ * Cached form of the AST. Either a {@code SerializedAst} object used by split functions as they can't be
+ * reparsed from source, or a soft reference to a {@code FunctionNode} for other functions (it is safe
+ * to be cleared as they can be reparsed).
+ */
+ private volatile Object cachedAst;
/** Token of this function within the source. */
private final long token;
@@ -128,7 +150,6 @@
* @param nestedFunctions nested function map
* @param externalScopeDepths external scope depths
* @param internalSymbols internal symbols to method, defined in its scope
- * @param serializedAst a serialized AST representation. Normally only used for split functions.
*/
public RecompilableScriptFunctionData(
final FunctionNode functionNode,
@@ -136,8 +157,7 @@
final AllocationStrategy allocationStrategy,
final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
final Map<String, Integer> externalScopeDepths,
- final Set<String> internalSymbols,
- final byte[] serializedAst) {
+ final Set<String> internalSymbols) {
super(functionName(functionNode),
Math.min(functionNode.getParameters().size(), MAX_ARITY),
@@ -161,7 +181,6 @@
nfn.setParent(this);
}
- this.serializedAst = serializedAst;
createLogger();
}
@@ -244,7 +263,7 @@
* @return parent data, or null if non exists and also null IF UNKNOWN.
*/
public RecompilableScriptFunctionData getParent() {
- return parent;
+ return parent;
}
void setParent(final RecompilableScriptFunctionData parent) {
@@ -358,13 +377,11 @@
return allocationStrategy.allocate(map);
}
- boolean isSerialized() {
- return serializedAst != null;
- }
-
FunctionNode reparse() {
- if (isSerialized()) {
- return deserialize();
+ final FunctionNode cachedFunction = getCachedAst();
+ if (cachedFunction != null) {
+ assert cachedFunction.isCached();
+ return cachedFunction;
}
final int descPosition = Token.descPosition(token);
@@ -391,7 +408,98 @@
return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName);
}
- private FunctionNode deserialize() {
+ private FunctionNode getCachedAst() {
+ final Object lCachedAst = cachedAst;
+ // Are we softly caching the AST?
+ if (lCachedAst instanceof Reference<?>) {
+ final FunctionNode fn = (FunctionNode)((Reference<?>)lCachedAst).get();
+ if (fn != null) {
+ // Yes we are - this is fast
+ return cloneSymbols(fn);
+ }
+ // Are we strongly caching a serialized AST (for split functions only)?
+ } else if (lCachedAst instanceof SerializedAst) {
+ final SerializedAst serializedAst = (SerializedAst)lCachedAst;
+ // Even so, are we also softly caching the AST?
+ final FunctionNode cachedFn = serializedAst.cachedAst.get();
+ if (cachedFn != null) {
+ // Yes we are - this is fast
+ return cloneSymbols(cachedFn);
+ }
+ final FunctionNode deserializedFn = deserialize(serializedAst.serializedAst);
+ // Softly cache after deserialization, maybe next time we won't need to deserialize
+ serializedAst.cachedAst = new SoftReference<>(deserializedFn);
+ return deserializedFn;
+ }
+ // No cached representation; return null for reparsing
+ return null;
+ }
+
+ /**
+ * Sets the AST to cache in this function
+ * @param astToCache the new AST to cache
+ */
+ public void setCachedAst(final FunctionNode astToCache) {
+ assert astToCache.getId() == functionNodeId; // same function
+ assert !(cachedAst instanceof SerializedAst); // Can't overwrite serialized AST
+
+ final boolean isSplit = astToCache.isSplit();
+ // If we're caching a split function, we're doing it in the eager pass, hence there can be no other
+ // cached representation already. In other words, isSplit implies cachedAst == null.
+ assert !isSplit || cachedAst == null; //
+
+ final FunctionNode symbolClonedAst = cloneSymbols(astToCache);
+ final Reference<FunctionNode> ref = new SoftReference<>(symbolClonedAst);
+ cachedAst = ref;
+
+ // Asynchronously serialize split functions.
+ if (isSplit) {
+ astSerializerExecutorService.execute(() -> {
+ cachedAst = new SerializedAst(symbolClonedAst, ref);
+ });
+ }
+ }
+
+ /**
+ * Creates the AST serializer executor service used for in-memory serialization of split functions' ASTs.
+ * It is created with an unbounded queue (so it can queue any number of pending tasks). Its core and max
+ * threads is the same, but they are all allowed to time out so when there's no work, they can all go
+ * away. The threads will be daemons, and they will time out if idle for a minute. Their priority is also
+ * slightly lower than normal priority as we'd prefer the CPU to keep running the program; serializing
+ * split function is a memory conservation measure (it allows us to release the AST), it can wait a bit.
+ * @return an executor service with above described characteristics.
+ */
+ private static ExecutorService createAstSerializerExecutorService() {
+ final int threads = Math.max(1, Options.getIntProperty("nashorn.serialize.threads", Runtime.getRuntime().availableProcessors() / 2));
+ final ThreadPoolExecutor service = new ThreadPoolExecutor(threads, threads, 1, TimeUnit.MINUTES, new LinkedBlockingDeque<>(),
+ (r) -> {
+ final Thread t = new Thread(r, "Nashorn AST Serializer");
+ t.setDaemon(true);
+ t.setPriority(Thread.NORM_PRIORITY - 1);
+ return t;
+ });
+ service.allowCoreThreadTimeOut(true);
+ return service;
+ }
+
+ /**
+ * A tuple of a serialized AST and a soft reference to a deserialized AST. This is used to cache split
+ * functions. Since split functions are altered from their source form, they can't be reparsed from
+ * source. While we could just use the {@code byte[]} representation in {@link RecompilableScriptFunctionData#cachedAst}
+ * we're using this tuple instead to also keep a deserialized AST around in memory to cut down on
+ * deserialization costs.
+ */
+ private static class SerializedAst {
+ private final byte[] serializedAst;
+ private volatile Reference<FunctionNode> cachedAst;
+
+ SerializedAst(final FunctionNode fn, final Reference<FunctionNode> cachedAst) {
+ this.serializedAst = AstSerializer.serialize(fn);
+ this.cachedAst = cachedAst;
+ }
+ }
+
+ private FunctionNode deserialize(final byte[] serializedAst) {
final ScriptEnvironment env = installer.getOwner();
final Timing timing = env._timing;
final long t1 = System.nanoTime();
@@ -402,6 +510,107 @@
}
}
+ private FunctionNode cloneSymbols(final FunctionNode fn) {
+ final IdentityHashMap<Symbol, Symbol> symbolReplacements = new IdentityHashMap<>();
+ final boolean cached = fn.isCached();
+ // blockDefinedSymbols is used to re-mark symbols defined outside the function as global. We only
+ // need to do this when we cache an eagerly parsed function (which currently means a split one, as we
+ // don't cache non-split functions from the eager pass); those already cached, or those not split
+ // don't need this step.
+ final Set<Symbol> blockDefinedSymbols = fn.isSplit() && !cached ? Collections.newSetFromMap(new IdentityHashMap<>()) : null;
+ FunctionNode newFn = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+
+ private Symbol getReplacement(final Symbol original) {
+ if (original == null) {
+ return null;
+ }
+ final Symbol existingReplacement = symbolReplacements.get(original);
+ if (existingReplacement != null) {
+ return existingReplacement;
+ }
+ final Symbol newReplacement = original.clone();
+ symbolReplacements.put(original, newReplacement);
+ return newReplacement;
+ }
+
+ @Override
+ public Node leaveIdentNode(final IdentNode identNode) {
+ final Symbol oldSymbol = identNode.getSymbol();
+ if (oldSymbol != null) {
+ final Symbol replacement = getReplacement(oldSymbol);
+ return identNode.setSymbol(replacement);
+ }
+ return identNode;
+ }
+
+ @Override
+ public Node leaveForNode(final ForNode forNode) {
+ return ensureUniqueLabels(forNode.setIterator(lc, getReplacement(forNode.getIterator())));
+ }
+
+ @Override
+ public Node leaveSwitchNode(final SwitchNode switchNode) {
+ return ensureUniqueLabels(switchNode.setTag(lc, getReplacement(switchNode.getTag())));
+ }
+
+ @Override
+ public Node leaveTryNode(final TryNode tryNode) {
+ return ensureUniqueLabels(tryNode.setException(lc, getReplacement(tryNode.getException())));
+ }
+
+ @Override
+ public boolean enterBlock(final Block block) {
+ for(final Symbol symbol: block.getSymbols()) {
+ final Symbol replacement = getReplacement(symbol);
+ if (blockDefinedSymbols != null) {
+ blockDefinedSymbols.add(replacement);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public Node leaveBlock(final Block block) {
+ return ensureUniqueLabels(block.replaceSymbols(lc, symbolReplacements));
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ return functionNode.setParameters(lc, functionNode.visitParameters(this));
+ }
+
+ @Override
+ protected Node leaveDefault(final Node node) {
+ return ensureUniqueLabels(node);
+ };
+
+ private Node ensureUniqueLabels(final Node node) {
+ // If we're returning a cached AST, we must also ensure unique labels
+ return cached ? node.ensureUniqueLabels(lc) : node;
+ }
+ });
+
+ if (blockDefinedSymbols != null) {
+ // Mark all symbols not defined in blocks as globals
+ Block newBody = null;
+ for(final Symbol symbol: symbolReplacements.values()) {
+ if(!blockDefinedSymbols.contains(symbol)) {
+ assert symbol.isScope(); // must be scope
+ assert externalScopeDepths.containsKey(symbol.getName()); // must be known to us as an external
+ // Register it in the function body symbol table as a new global symbol
+ symbol.setFlags((symbol.getFlags() & ~Symbol.KINDMASK) | Symbol.IS_GLOBAL);
+ if (newBody == null) {
+ newBody = newFn.getBody().copyWithNewSymbols();
+ newFn = newFn.setBody(null, newBody);
+ }
+ assert newBody.getExistingSymbol(symbol.getName()) == null; // must not be defined in the body already
+ newBody.putSymbol(symbol);
+ }
+ }
+ }
+ return newFn.setCached(null);
+ }
+
private boolean getFunctionFlag(final int flag) {
return (functionFlags & flag) != 0;
}
@@ -512,9 +721,9 @@
final FunctionNode fn = reparse();
final Compiler compiler = getCompiler(fn, actualCallSiteType, runtimeScope);
final FunctionNode compiledFn = compiler.compile(fn,
- isSerialized() ? CompilationPhases.COMPILE_ALL_SERIALIZED : CompilationPhases.COMPILE_ALL);
+ fn.isCached() ? CompilationPhases.COMPILE_ALL_CACHED : CompilationPhases.COMPILE_ALL);
- if (persist && !compiledFn.getFlag(FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION)) {
+ if (persist && !compiledFn.hasApplyToCallSpecialization()) {
compiler.persistClassInfo(cacheKey, compiledFn);
}
return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Mon Sep 14 07:03:04 2015 +0000
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@@ -70,6 +71,9 @@
/** EXIT name - special property used by $EXEC API. */
public static final String EXIT_NAME = "$EXIT";
+ /** THROW_ON_ERROR name - special property of the $EXEC function used by $EXEC API. */
+ public static final String THROW_ON_ERROR_NAME = "throwOnError";
+
/** Names of special properties used by $ENV API. */
public static final String ENV_NAME = "$ENV";
@@ -247,6 +251,19 @@
}
}
+ // if we got a non-zero exit code ("failure"), then we have to decide to throw error or not
+ if (exit != 0) {
+ // get the $EXEC function object from the global object
+ final Object exec = global.get(EXEC_NAME);
+ assert exec instanceof ScriptObject : EXEC_NAME + " is not a script object!";
+
+ // Check if the user has set $EXEC.throwOnError property to true. If so, throw RangeError
+ // If that property is not set or set to false, then silently proceed with the rest.
+ if (JSType.toBoolean(((ScriptObject)exec).get(THROW_ON_ERROR_NAME))) {
+ throw rangeError("exec.returned.non.zero", ScriptRuntime.safeToString(exit));
+ }
+ }
+
// Return the result from stdout.
return out;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java Mon Sep 14 07:02:50 2015 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- */
-
-package jdk.nashorn.internal.runtime.arrays;
-
-/**
- * Mechanism for communicating that something isn't a plain
- * numeric integer array index. This enables things like
- * array getters for the fast case in a try, basically
- * just consisting of an "array[index]" access without
- * any checks of boundary conditions that rarely happen
- */
-@SuppressWarnings("serial")
-class InvalidArrayIndexException extends Exception {
-
- private final Object index;
-
- InvalidArrayIndexException(final Object index) {
- super(index == null ? "null" : index.toString());
- this.index = index;
- }
-
- InvalidArrayIndexException(final int index) {
- this(Integer.valueOf(index));
- }
-
- InvalidArrayIndexException(final long index) {
- this(Long.valueOf(index));
- }
-
- InvalidArrayIndexException(final double index) {
- this(Double.valueOf(index));
- }
-
- @Override
- public String toString() {
- return index.toString();
- }
-
- Object getIndex() {
- return index;
- }
-
-}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/AdaptationException.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/AdaptationException.java Mon Sep 14 07:03:04 2015 +0000
@@ -30,6 +30,7 @@
private final AdaptationResult adaptationResult;
AdaptationException(final AdaptationResult.Outcome outcome, final String classList) {
+ super(null, null, false, false);
this.adaptationResult = new AdaptationResult(outcome, classList);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Mon Sep 14 07:03:04 2015 +0000
@@ -189,7 +189,7 @@
* @return true if the obj is an instance of @FunctionalInterface interface
*/
public static boolean isFunctionalInterfaceObject(final Object obj) {
- return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethod(obj.getClass()) != null);
+ return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethodName(obj.getClass()) != null);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Mon Sep 14 07:03:04 2015 +0000
@@ -79,10 +79,10 @@
}
// cache of @FunctionalInterface method of implementor classes
- private static final ClassValue<Method> FUNCTIONAL_IFACE_METHOD = new ClassValue<Method>() {
+ private static final ClassValue<String> FUNCTIONAL_IFACE_METHOD_NAME = new ClassValue<String>() {
@Override
- protected Method computeValue(final Class<?> type) {
- return findFunctionalInterfaceMethod(type);
+ protected String computeValue(final Class<?> type) {
+ return findFunctionalInterfaceMethodName(type);
}
};
@@ -107,19 +107,21 @@
// annotated interface. This way Java method, constructor references or
// implementations of java.util.function.* interfaces can be called as though
// those are script functions.
- final Method m = getFunctionalInterfaceMethod(self.getClass());
- if (m != null) {
+ final String name = getFunctionalInterfaceMethodName(self.getClass());
+ if (name != null) {
final MethodType callType = desc.getMethodType();
- // 'callee' and 'thiz' passed from script + actual arguments
- if (callType.parameterCount() != m.getParameterCount() + 2) {
- throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
- }
- return new GuardedInvocation(
- // drop 'thiz' passed from the script.
- MH.dropArguments(linkerServices.filterInternalObjects(desc.getLookup().unreflect(m)), 1,
- callType.parameterType(1)), Guards.getInstanceOfGuard(
- m.getDeclaringClass())).asTypeSafeReturn(
- new NashornBeansLinkerServices(linkerServices), callType);
+ // drop callee (Undefined ScriptFunction) and change the request to be dyn:callMethod:<name>
+ final NashornCallSiteDescriptor newDesc = NashornCallSiteDescriptor.get(desc.getLookup(),
+ "dyn:callMethod:" + name, desc.getMethodType().dropParameterTypes(1, 2),
+ NashornCallSiteDescriptor.getFlags(desc));
+ final GuardedInvocation gi = getGuardedInvocation(beansLinker,
+ linkRequest.replaceArguments(newDesc, linkRequest.getArguments()),
+ new NashornBeansLinkerServices(linkerServices));
+
+ // drop 'thiz' passed from the script.
+ return gi.replaceMethods(
+ MH.dropArguments(linkerServices.filterInternalObjects(gi.getInvocation()), 1, callType.parameterType(1)),
+ gi.getGuard());
}
}
return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
@@ -163,7 +165,7 @@
return arg instanceof ConsString ? arg.toString() : arg;
}
- private static Method findFunctionalInterfaceMethod(final Class<?> clazz) {
+ private static String findFunctionalInterfaceMethodName(final Class<?> clazz) {
if (clazz == null) {
return null;
}
@@ -179,20 +181,20 @@
// return the first abstract method
for (final Method m : iface.getMethods()) {
if (Modifier.isAbstract(m.getModifiers())) {
- return m;
+ return m.getName();
}
}
}
}
// did not find here, try super class
- return findFunctionalInterfaceMethod(clazz.getSuperclass());
+ return findFunctionalInterfaceMethodName(clazz.getSuperclass());
}
// Returns @FunctionalInterface annotated interface's single abstract
- // method. If not found, returns null.
- static Method getFunctionalInterfaceMethod(final Class<?> clazz) {
- return FUNCTIONAL_IFACE_METHOD.get(clazz);
+ // method name. If not found, returns null.
+ static String getFunctionalInterfaceMethodName(final Class<?> clazz) {
+ return FUNCTIONAL_IFACE_METHOD_NAME.get(clazz);
}
static MethodHandleTransformer createHiddenObjectFilter() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java Mon Sep 14 07:03:04 2015 +0000
@@ -24,6 +24,6 @@
private static final long serialVersionUID = -6027192180014164667L;
public JOniException(final String message) {
- super(message);
+ super(message, null, false, false);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties Mon Sep 14 07:03:04 2015 +0000
@@ -163,6 +163,7 @@
range.error.invalid.date=Invalid Date
range.error.too.many.errors=Script contains too many errors: {0} errors
range.error.concat.string.too.big=Concatenated String is too big
+range.error.exec.returned.non.zero=$EXEC returned non-zero exit code: {0}
reference.error.not.defined="{0}" is not defined
reference.error.cant.be.used.as.lhs="{0}" can not be used as the left-hand side of assignment
--- a/nashorn/test/script/basic/JDK-8043232.js.EXPECTED Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/test/script/basic/JDK-8043232.js.EXPECTED Mon Sep 14 07:03:04 2015 +0000
@@ -1,14 +1,28 @@
bcd
-[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)]
+[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)]
red
TypeError: No such Java class: java.lang.NonExistent
TypeError: No such Java constructor: Object(String)
TypeError: Java constructor signature invalid: Object()xxxxx
TypeError: Java constructor signature invalid: Object(
TypeError: Java constructor signature invalid: Object)
-TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cannot be used as a constructor.
-TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cannot be used as a constructor.
-TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] requires "new".
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ String java.lang.System.getProperty(String,String)
+ String java.lang.System.getProperty(String)
+] cannot be used as a constructor.
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ void java.io.PrintStream.println()
+ void java.io.PrintStream.println(boolean)
+ void java.io.PrintStream.println(char)
+ void java.io.PrintStream.println(char[])
+ void java.io.PrintStream.println(double)
+ void java.io.PrintStream.println(float)
+ void java.io.PrintStream.println(int)
+ void java.io.PrintStream.println(long)
+ void java.io.PrintStream.println(Object)
+ void java.io.PrintStream.println(String)
+] cannot be used as a constructor.
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new".
TypeError: No such Java constructor: Runnable()
TypeError: No such Java constructor: Runnable(int)
java.lang.InstantiationException: java.io.InputStream
--- a/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Mon Sep 14 07:03:04 2015 +0000
@@ -1,10 +1,10 @@
abc
-[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)]
+[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)]
ava
TypeError: null is not a function
TypeError: null is not a function
TypeError: null is not a function
-TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] requires "new".
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new".
TypeError: null is not a function
TypeError: null is not a function
java.lang.InstantiationException: java.io.InputStream
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068901.js Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8068901: Surprising behavior with more than one functional interface on a class
+ *
+ * @test
+ * @run
+ */
+
+var Consumer = java.util.function.Consumer;
+var JFunction = java.util.function.Function;
+
+var fc = new (Java.extend(JFunction, Consumer))({
+ apply: function(x) { print("fc invoked as a function") },
+ accept: function(x) { print("fc invoked as a consumer") }
+});
+
+var c = new Consumer(function(x) { print("c invoked as a consumer") });
+
+var cf = new (Java.extend(Consumer, JFunction))({
+ apply: function(x) { print("cf invoked as a function") },
+ accept: function(x) { print("cf invoked as a consumer") }
+});
+
+var f = new JFunction(function(x) { print("f invoked as a function") });
+
+for each(x in [fc, c, fc, cf, f, cf, c, fc, f, cf]) { x(null); }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068901.js.EXPECTED Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,10 @@
+fc invoked as a function
+c invoked as a consumer
+fc invoked as a function
+cf invoked as a consumer
+f invoked as a function
+cf invoked as a consumer
+c invoked as a consumer
+fc invoked as a function
+f invoked as a function
+cf invoked as a consumer
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068903.js Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8068903: Can't invoke vararg @FunctionalInterface methods
+ *
+ * @test
+ * @run
+ */
+
+var vc = new (Java.type("jdk.nashorn.test.models.VarArgConsumer"))(
+ function(x) {
+ Assert.assertTrue(x.length == 3);
+ Assert.assertTrue(x[0] == 1);
+ Assert.assertTrue(x[1] == 2);
+ Assert.assertTrue(x[2] == 3);
+ }
+);
+
+vc(1, 2, 3);
--- a/nashorn/test/script/basic/JDK-8079470.js.EXPECTED Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/test/script/basic/JDK-8079470.js.EXPECTED Mon Sep 14 07:03:04 2015 +0000
@@ -1,2 +1,2 @@
-TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod File java.io.File.java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures.
-TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures.
+TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures.
+TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8134731.js Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8134731: `Function.prototype.apply` interacts incorrectly with `arguments`
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+ return (function(f){
+ return function(a1, a2, a3, a4){
+ return (f.apply(this, arguments));
+ }
+ })(function(){
+ return arguments.length;
+ })
+}
+
+Assert.assertTrue(func()() == 0);
+Assert.assertTrue(func()(33) == 1);
+Assert.assertTrue(func()(33, true) == 2);
+Assert.assertTrue(func()(33, true, "hello") == 3);
+Assert.assertTrue(func()(33, true, "hello", "world") == 4);
+Assert.assertTrue(func()(33, true, "hello", "world", 42) == 5);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8134865.js Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8134865: Need to restore for container block from lexical context in finally
+ *
+ * @test
+ * @option --language=es6
+ */
+
+try {
+ eval("function f() { for (x : y) { } }");
+ throw "should not reach here";
+} catch (e) {
+ if (!(e instanceof SyntaxError)) throw e;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8134939.js Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8134939: Improve toString method of Dynalink OverloadedDynamicMethod
+ *
+ * @test
+ * @run
+ */
+
+var overloadedSetter = new (Java.type("jdk.nashorn.test.models.OverloadedSetter"));
+
+Assert.assertEquals(String(overloadedSetter.foo),
+ "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" +
+ " String jdk.nashorn.test.models.OverloadedSetter.foo(String)\n" +
+ " void jdk.nashorn.test.models.OverloadedSetter.foo(int)\n" +
+ "]");
+
+Assert.assertEquals(String(overloadedSetter.setColor),
+ "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" +
+ " void jdk.nashorn.test.models.OverloadedSetter.setColor(int)\n" +
+ " void jdk.nashorn.test.models.OverloadedSetter.setColor(String)\n" +
+ "]");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/numeric-literals.js Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8134873: ECMAScript 6 Numeric Literals
+ *
+ * @test
+ * @option --language=es6
+ */
+
+function assertEquals(expected, actual) {
+ if (expected !== actual) {
+ throw new Error("expected: " + expected + ", actual: " + actual);
+ }
+}
+
+assertEquals(0b0, 0);
+assertEquals(0B0, 0);
+assertEquals(0b01, 1);
+assertEquals(0B10, 2);
+assertEquals(0b11111111, 255);
+assertEquals(0b11111111111111111111111111111111, 4294967295);
+
+assertEquals(0o0, 0);
+assertEquals(0O0, 0);
+assertEquals(0o01, 1);
+assertEquals(0O10, 8);
+assertEquals(0o777, 511);
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/trusted/JDK-8087292.js Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8087292: nashorn should have a "fail-fast" option for scripting, analog to bash "set -e"
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+function tryExec() {
+ try {
+ `java`
+ } catch (e) {
+ print(e);
+ }
+
+ // make sure we got non-zero ("failure") exit code!
+ if ($EXIT == 0) {
+ print("Error: expected $EXIT code to be non-zero");
+ }
+}
+
+// no exception now!
+tryExec();
+
+// turn on error with non-zero exit code
+$EXEC.throwOnError = true;
+tryExec();
+
+// no exception after this
+$EXEC.throwOnError = false;
+tryExec();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/trusted/JDK-8087292.js.EXPECTED Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,1 @@
+RangeError: $EXEC returned non-zero exit code: 1
--- a/nashorn/test/script/trusted/classfilter.js.EXPECTED Mon Sep 14 07:02:50 2015 +0200
+++ b/nashorn/test/script/trusted/classfilter.js.EXPECTED Mon Sep 14 07:03:04 2015 +0000
@@ -4,7 +4,18 @@
typeof java.util.Map evalutes to function
typeof java.util.HashMap evalutes to function
var m = new java.util.HashMap(); m.put('foo', 42); m evalutes to {foo=42}
-java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println]
+java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ void java.io.PrintStream.println()
+ void java.io.PrintStream.println(boolean)
+ void java.io.PrintStream.println(char)
+ void java.io.PrintStream.println(char[])
+ void java.io.PrintStream.println(double)
+ void java.io.PrintStream.println(float)
+ void java.io.PrintStream.println(int)
+ void java.io.PrintStream.println(long)
+ void java.io.PrintStream.println(Object)
+ void java.io.PrintStream.println(String)
+]
java.lang.System.exit evalutes to [jdk.internal.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)]
new javax.script.SimpleBindings throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.SimpleBindings
Java.type('javax.script.ScriptContext') throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.ScriptContext
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/test/models/VarArgConsumer.java Mon Sep 14 07:03:04 2015 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package jdk.nashorn.test.models;
+
+/**
+ * Simple function interface with a varargs SAM method.
+ */
+@FunctionalInterface
+public interface VarArgConsumer {
+ public void apply(Object... o);
+}
+