diff --git a/.hgtags b/.hgtags index af2c1e3c0a5..602ce40b2cb 100644 --- a/.hgtags +++ b/.hgtags @@ -195,3 +195,6 @@ adb5171c554e14cd86f618b5584f6e3d693d5889 jdk8-b69 a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71 6725b3961f987cf40f446d1c11cd324a3bec545f jdk8-b72 fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73 +f627eff819628822a0777af8062244352f2a29cf jdk8-b74 +f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75 +f407160c280d1c5b00d314c535441ac26f195fee jdk8-b76 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 8555b3366ec..b6c4116ea62 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -195,3 +195,6 @@ cdb401a60cea6ad5ef3f498725ed1decf8dda1ea jdk8-b68 51ad2a34342055333eb5f36e2fb514b027895708 jdk8-b71 c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72 93b9664f97eeb6f89397a8842318ebacaac9feb9 jdk8-b73 +b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74 +2a713921952cbd77a1e699626976cb6cdfe3e57e jdk8-b75 +278af9fc67e7eba2884936b49ec07345f423aabb jdk8-b76 diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 2ab9711e3d3..d53e56ec100 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -3723,7 +3723,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1358499442 +DATE_WHEN_GENERATED=1359971740 ############################################################################### # @@ -10778,7 +10778,8 @@ if test "x$with_milestone" = xyes; then as_fn_error $? "Milestone must have a value" "$LINENO" 5 elif test "x$with_milestone" != x; then MILESTONE="$with_milestone" -else +fi +if test "x$MILESTONE" = x; then MILESTONE=internal fi @@ -29247,6 +29248,12 @@ fi fi +# AC_PATH_XTRA creates X_LIBS and sometimes adds -R flags. When cross compiling +# this doesn't make sense so we remove it. +if test "x$COMPILE_TYPE" = xcross; then + X_LIBS=`$ECHO $X_LIBS | $SED 's/-R \{0,1\}[^ ]*//g'` +fi + if test "x$no_x" = xyes && test "x$X11_NOT_NEEDED" != xyes; then # Print a helpful message on how to acquire the necessary build dependency. diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index d9f188d65d8..48eb3f85c0e 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -389,7 +389,8 @@ if test "x$with_milestone" = xyes; then AC_MSG_ERROR([Milestone must have a value]) elif test "x$with_milestone" != x; then MILESTONE="$with_milestone" -else +fi +if test "x$MILESTONE" = x; then MILESTONE=internal fi diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index e1fea0726d6..91b0a846e5f 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -136,6 +136,12 @@ fi AC_PATH_X AC_PATH_XTRA +# AC_PATH_XTRA creates X_LIBS and sometimes adds -R flags. When cross compiling +# this doesn't make sense so we remove it. +if test "x$COMPILE_TYPE" = xcross; then + X_LIBS=`$ECHO $X_LIBS | $SED 's/-R \{0,1\}[[^ ]]*//g'` +fi + if test "x$no_x" = xyes && test "x$X11_NOT_NEEDED" != xyes; then HELP_MSG_MISSING_DEPENDENCY([x11]) AC_MSG_ERROR([Could not find X11 libraries. $HELP_MSG]) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 5fde9e7cf16..ad882958d9d 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -434,6 +434,12 @@ NATIVE2ASCII=@FIXPATH@ $(BOOT_JDK)/bin/native2ascii JARSIGNER=@FIXPATH@ $(BOOT_JDK)/bin/jarsigner +# You run the new javac using the boot jdk with $(BOOT_JDK)/bin/java $(NEW_JAVAC) ... +BOOTSTRAP_JAVAC_JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar +BOOTSTRAP_JAVAC_ARGS:="-Xbootclasspath/p:$(BOOTSTRAP_JAVAC_JAR)" -cp $(BOOTSTRAP_JAVAC_JAR) +NEW_JAVAC = $(BOOTSTRAP_JAVAC_ARGS) com.sun.tools.javac.Main +NEW_JAVADOC = $(BOOTSTRAP_JAVAC_ARGS) com.sun.tools.javadoc.Main + # Base flags for RC # Guarding this against resetting value. Legacy make files include spec multiple # times. diff --git a/common/bin/compare.sh b/common/bin/compare.sh index 1e1ceb08ae6..0ba46727acc 100644 --- a/common/bin/compare.sh +++ b/common/bin/compare.sh @@ -350,9 +350,15 @@ compare_zip_file() { OTHER_DIR=$2 WORK_DIR=$3 ZIP_FILE=$4 + # Optionally provide different name for other zipfile + OTHER_ZIP_FILE=$5 THIS_ZIP=$THIS_DIR/$ZIP_FILE - OTHER_ZIP=$OTHER_DIR/$ZIP_FILE + if [ -n "$OTHER_ZIP_FILE" ]; then + OTHER_ZIP=$OTHER_DIR/$OTHER_ZIP_FILE + else + OTHER_ZIP=$OTHER_DIR/$ZIP_FILE + fi THIS_SUFFIX="${THIS_ZIP##*.}" OTHER_SUFFIX="${OTHER_ZIP##*.}" @@ -962,6 +968,9 @@ if [ -z "$1" ] || [ "$1" = "-h" ] || [ "$1" = "-?" ] || [ "$1" = "/h" ] || [ "$1 echo "[FILTER] List filenames in the image to compare, works for jars, zips, libs and execs" echo "Example:" echo "bash ./common/bin/compareimages.sh CodePointIM.jar" + echo "" + echo "-2zips Compare two zip files only" + echo "" exit 10 fi @@ -1023,6 +1032,13 @@ while [ -n "$1" ]; do -execs) CMP_EXECS=true ;; + -2zips) + CMP_2_ZIPS=true + THIS_FILE=$2 + OTHER_FILE=$3 + shift + shift + ;; *) CMP_NAMES=false CMP_PERMS=false @@ -1041,6 +1057,18 @@ while [ -n "$1" ]; do shift done +if [ "$CMP_2_ZIPS" = "true" ]; then + THIS_DIR="$(dirname $THIS_FILE)" + THIS_DIR="$(cd "$THIS_DIR" && pwd )" + OTHER_DIR="$(dirname $OTHER_FILE)" + OTHER_DIR="$(cd "$OTHER_DIR" && pwd )" + THIS_FILE_NAME="$(basename $THIS_FILE)" + OTHER_FILE_NAME="$(basename $OTHER_FILE)" + echo Comparing $THIS_DIR/$THIS_FILE_NAME and $OTHER_DIR/$OTHER_FILE_NAME + compare_zip_file $THIS_DIR $OTHER_DIR $COMPARE_ROOT/2zips $THIS_FILE_NAME $OTHER_FILE_NAME + exit +fi + if [ "$CMP_NAMES" = "false" ] && [ "$CMP_TYPES" = "false" ] && [ "$CMP_PERMS" = "false" ] && [ "$CMP_GENERAL" = "false" ] && [ "$CMP_ZIPS" = "false" ] && [ "$CMP_JARS" = "false" ] && [ "$CMP_LIBS" = "false" ] && [ "$CMP_EXECS" = "false" ]; then CMP_NAMES=true CMP_PERMS=true diff --git a/common/bin/compare_exceptions.sh.incl b/common/bin/compare_exceptions.sh.incl index 8b2b64dec24..3b79a526f56 100644 --- a/common/bin/compare_exceptions.sh.incl +++ b/common/bin/compare_exceptions.sh.incl @@ -887,6 +887,17 @@ ACCEPTED_SMALL_SIZE_DIFF=" ./jre/bin/unpack200.exe " +# jabswitch.exe is compiled and linked with incremental turned on in the old +# build. This makes no sense, so it's turned off in the new build. +ACCEPTED_SIZE_DIFF=" +./bin/jabswitch.exe +./jre/bin/jabswitch.exe +" +ACCEPTED_DIS_DIFF=" +./bin/jabswitch.exe +./jre/bin/jabswitch.exe +" + # On windows, there are unavoidable allignment issues making # a perfect disasm diff impossible. Filter out the following: # * Random parts of C++ symbols (this is a bit greedy, but does the trick) diff --git a/common/makefiles/IdlCompilation.gmk b/common/makefiles/IdlCompilation.gmk index 6dc5fee2999..2eb77dd3beb 100644 --- a/common/makefiles/IdlCompilation.gmk +++ b/common/makefiles/IdlCompilation.gmk @@ -71,7 +71,7 @@ define add_idl_package $4 $(RM) -f $$(addprefix $3/$$($4_TMPDIR)/,$6) $(CP) -rp $3/$$($4_TMPDIR)/* $3 - ($(CD) $3/$$($4_TMPDIR); find . -type f | sed 's!\./!$3/!g' | awk '{ print $$$$1 ": $4" }' > $5) + ($(CD) $3/$$($4_TMPDIR) && $(FIND) . -type f | $(SED) 's!\./!$3/!g' | $(NAWK) '{ print $$$$1 ": $4" }' > $5) $(RM) -rf $3/$$($4_TMPDIR) endef diff --git a/common/makefiles/JavaCompilation.gmk b/common/makefiles/JavaCompilation.gmk index 59adc339779..27257183ac6 100644 --- a/common/makefiles/JavaCompilation.gmk +++ b/common/makefiles/JavaCompilation.gmk @@ -42,8 +42,8 @@ endif FALSE_FIND_PATTERN:=-name FILE_NAME_THAT_DOESNT_EXIST define SetupJavaCompiler - # param 1 is for example BOOT_JAVAC or NEW_JAVAC - # This is the name later used to decide which java compiler to use. + # param 1 is for example GENERATE_OLD_BYTECODE or GENERATE_NEW_JDKBYTECODE + # This is the name of the compiler setup. # param 2-9 are named args. # JVM:=The jvm used to run the javac/javah command # JAVAC:=The javac jar and bootstrap classpath changes, or just bin/javac if JVM is left out @@ -143,8 +143,8 @@ define SetupArchive ifneq (,$2) $1_DEPS:=$2 else - $1_DEPS:=$$(filter $$(addprefix %,$$($1_FIND_PATTERNS)),\ - $$(call CacheFind $$($1_SRCS))) + $1_DEPS:=$$(filter $$(addprefix %,$$($1_SUFFIXES)),\ + $$(call CacheFind,$$($1_SRCS))) ifneq (,$$($1_GREP_INCLUDE_PATTERNS)) $1_DEPS:=$$(filter $$(addsuffix %,$$($1_GREP_INCLUDE_PATTERNS)),$$($1_DEPS)) endif @@ -487,10 +487,10 @@ define SetupJavaCompilation # Using sjavac to compile. $1 := $$($1_ALL_COPY_TARGETS) $$($1_ALL_COPY_CLEAN_TARGETS) $$($1_BIN)/javac_state - # Create SJAVAC variable, - # expects $1_JAVAC to be "bootclasspathprepend -jar ...javac.jar" - # and it is rewritten into "bootclasspathprepend com.sun.tools.sjavac.Main" - $1_SJAVAC:=$$(word 1,$$($1_JAVAC)) -cp $$(word 3,$$($1_JAVAC)) com.sun.tools.sjavac.Main + # Create SJAVAC variable form JAVAC variable. Expects $1_JAVAC to be + # "bootclasspathprepend -cp .../javac.jar com.sun.tools.javac.Main" + # and javac is simply replaced with sjavac. + $1_SJAVAC:=$$(subst com.sun.tools.javac.Main,com.sun.tools.sjavac.Main,$$($1_JAVAC)) # Set the $1_REMOTE to spawn a background javac server. $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC)))) diff --git a/common/makefiles/Jprt.gmk b/common/makefiles/Jprt.gmk index b8bc418fbae..c70cf8872b4 100644 --- a/common/makefiles/Jprt.gmk +++ b/common/makefiles/Jprt.gmk @@ -179,27 +179,52 @@ jprt_bundle: $(JPRT_ARCHIVE_BUNDLE) $(JPRT_ARCHIVE_BUNDLE): bundles $(MKDIR) -p $(@D) $(RM) $@ - $(CP) $(BUILD_OUTPUT)/bundles/j2sdk-image.zip $@ + $(CP) $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip $@ -# This target must be called in the context of a SPEC file -bundles: all +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) + SRC_JDK_IMAGE_DIR := $(JDK_OVERLAY_IMAGE_DIR) + SRC_JRE_IMAGE_DIR := $(JRE_OVERLAY_IMAGE_DIR) +else + SRC_JDK_IMAGE_DIR := $(JDK_IMAGE_DIR) + SRC_JRE_IMAGE_DIR := $(JRE_IMAGE_DIR) +endif +SRC_JDK_BUNDLE_DIR := $(JDK_BUNDLE_DIR) +SRC_JRE_BUNDLE_DIR := $(JRE_BUNDLE_DIR) + +# Bundle up the images +bundles: all bundles-only +bundles-only: start-make @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles -ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) - $(CD) $(JDK_OVERLAY_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2sdk-image.zip . - $(CD) $(JRE_OVERLAY_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2re-image.zip . -else - $(CD) $(JDK_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2sdk-image.zip . - $(CD) $(JRE_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2re-image.zip . + $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip . + $(CD) $(SRC_JRE_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip . if [ -d $(BUILD_OUTPUT)/install/bundles ] ; then \ $(CD) $(BUILD_OUTPUT)/install/bundles && $(ZIP) -q -r $(JPRT_ARCHIVE_INSTALL_BUNDLE) . ; \ fi + @$(call TargetExit) + +# Copy images to one unified location regardless of platform etc. +final-images: all final-images-only +final-images-only: start-make + @$(call TargetEnter) + $(RM) -r $(BUILD_OUTPUT)/final-images + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JRE_IMAGE_SUBDIR) + $(CP) -R -P $(SRC_JDK_IMAGE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR)/ + $(CP) -R -P $(SRC_JRE_IMAGE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JRE_IMAGE_SUBDIR)/ +ifeq ($(OPENJDK_TARGET_OS),macosx) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_BUNDLE_SUBDIR) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JRE_BUNDLE_SUBDIR) + $(CP) -R -P $(SRC_JDK_BUNDLE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JDK_BUNDLE_SUBDIR)/ + $(CP) -R -P $(SRC_JRE_BUNDLE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JRE_BUNDLE_SUBDIR)/ endif @$(call TargetExit) + # Keep track of phony targets PHONY_LIST += jprt_build_product jprt_build_fastdebug jprt_build_debug \ - jprt_build_generic bundles jprt_bundle + jprt_build_generic bundles jprt_bundle \ + final-images final-images-only ########################################################################### # Phony targets diff --git a/common/makefiles/Main.gmk b/common/makefiles/Main.gmk index c96747f090c..ded49ff55e4 100644 --- a/common/makefiles/Main.gmk +++ b/common/makefiles/Main.gmk @@ -75,7 +75,14 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) all: overlay-images endif -start-make: +# Setup a rule for SPEC file that fails if executed. This check makes sure the configuration +# is up to date after changes to configure +$(SPEC): $(wildcard $(SRC_ROOT)/common/autoconf/*) + @$(ECHO) ERROR: $(SPEC) is not up to date + @$(ECHO) Please rerun configure! + @if test "x$(IGNORE_OLD_CONFIG)" != "xtrue"; then exit 1; fi + +start-make: $(SPEC) @$(call AtMakeStart) langtools: langtools-only diff --git a/common/makefiles/javadoc/CORE_PKGS.gmk b/common/makefiles/javadoc/CORE_PKGS.gmk index dcfda026ded..b91aae1b650 100644 --- a/common/makefiles/javadoc/CORE_PKGS.gmk +++ b/common/makefiles/javadoc/CORE_PKGS.gmk @@ -127,6 +127,11 @@ CORE_PKGS = \ java.sql \ java.text \ java.text.spi \ + java.time \ + java.time.temporal \ + java.time.calendar \ + java.time.format \ + java.time.zone \ java.util \ java.util.concurrent \ java.util.concurrent.atomic \ diff --git a/common/makefiles/javadoc/Javadoc.gmk b/common/makefiles/javadoc/Javadoc.gmk index cee44b958fe..1d798120708 100644 --- a/common/makefiles/javadoc/Javadoc.gmk +++ b/common/makefiles/javadoc/Javadoc.gmk @@ -1,4 +1,4 @@ -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -46,14 +46,11 @@ HOTSPOT_DOCS_IMPORT_PATH=$(HOTSPOT_OUTPUTDIR)/docs BUILD_NUMBER=$(JDK_BUILD_NUMBER) -BOOT_JAVA_CMD=$(JAVA) - -JAVADOC_JAR = $(LANGTOOLS_DIST)/bootstrap/lib/javadoc.jar -JAVADOC_CMD = $(BOOT_JAVA_CMD) \ +JAVADOC_CMD = $(JAVA) \ -Xmx1024m \ -Djava.awt.headless=true \ - "-Xbootclasspath/p:$(JAVADOC_JAR)" \ - -jar $(JAVADOC_JAR) -bootclasspath $(JDK_OUTPUTDIR)/classes + $(NEW_JAVADOC) \ + -bootclasspath $(JDK_OUTPUTDIR)/classes # Copyright year for beginning of Java and some of the apis # (Needed when creating the javadocs) @@ -269,6 +266,7 @@ COMMON_JAVADOCFLAGS = \ -quiet \ -use \ -keywords \ + -Xdoclint:none \ $(ADDITIONAL_JAVADOCFLAGS) ifdef OPENJDK diff --git a/corba/.hgtags b/corba/.hgtags index 1a3ee17d1bb..c292f1b787d 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -195,3 +195,6 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59 8171d23e914d758836527b80b06debcfdb718f2d jdk8-b71 cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72 191afde59e7be0e1a1d76d06f2a32ff17444f0ec jdk8-b73 +2132845cf5f717ff5c240a2431c0c0e03e66e3a5 jdk8-b74 +d4e68ce17795601017ac2f952baad7272942c36e jdk8-b75 +58be6ca3c0603882a1ec478724e337aac85e0da0 jdk8-b76 diff --git a/corba/makefiles/BuildCorba.gmk b/corba/makefiles/BuildCorba.gmk index 246c5b9bcec..b177ff2d212 100644 --- a/corba/makefiles/BuildCorba.gmk +++ b/corba/makefiles/BuildCorba.gmk @@ -35,8 +35,6 @@ include MakeBase.gmk include JavaCompilation.gmk include IdlCompilation.gmk -JAVAC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar # The Corba sources are old and generates a LOT of warnings. # Disable these using Xlint, until someone cares to fix them. DISABLE_CORBA_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-serial,-fallthrough,-cast,-rawtypes,-static,-dep-ann @@ -46,7 +44,7 @@ DISABLE_CORBA_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-serial,-fallthrough, # Thus we force the target bytecode to the boot jdk bytecode. $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=$(BOOT_JDK_SOURCETARGET) -bootclasspath $(BOOT_RTJAR) $(DISABLE_CORBA_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -56,7 +54,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-cp $(BOOT_TOOLSJAR) -XDignore.symbol.file=true $(DISABLE_CORBA_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 617e00e138a..da10e708478 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -308,3 +308,9 @@ e94068d4ff52849c8aa0786a53a59b63d1312a39 jdk8-b70 d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 1e129851479e4f5df439109fca2c7be1f1613522 hs25-b15 11619f33cd683c2f1d6ef72f1c6ff3dacf5a9f1c jdk8-b73 +70c89bd6b895a10d25ca70e08093c09ff2005fda hs25-b16 +1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 +b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 +6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75 +20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76 +412d722168bc23f8e6d98995202728678561417f hs25-b18 diff --git a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c index 5b49294e975..1d3c3bbd027 100644 --- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c +++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c @@ -280,7 +280,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo return (err == PS_OK)? array : 0; } -#if defined(i386) || defined(ia64) || defined(amd64) || defined(sparc) || defined(sparcv9) +#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 (JNIEnv *env, jobject this_obj, jint lwp_id) { @@ -299,9 +299,6 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo #ifdef i386 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #endif -#ifdef ia64 -#define NPRGREG IA64_REG_COUNT -#endif #ifdef amd64 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG #endif @@ -336,13 +333,6 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo #endif /* i386 */ -#if ia64 - regs = (*env)->GetLongArrayElements(env, array, &isCopy); - for (i = 0; i < NPRGREG; i++ ) { - regs[i] = 0xDEADDEAD; - } -#endif /* ia64 */ - #ifdef amd64 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg diff --git a/hotspot/agent/src/os/linux/libproc.h b/hotspot/agent/src/os/linux/libproc.h index 5f583631c08..4cde0c19d76 100644 --- a/hotspot/agent/src/os/linux/libproc.h +++ b/hotspot/agent/src/os/linux/libproc.h @@ -79,14 +79,6 @@ combination of ptrace and /proc calls. *************************************************************************************/ -#ifdef ia64 -struct user_regs_struct { -/* copied from user.h which doesn't define this in a struct */ - -#define IA64_REG_COUNT (EF_SIZE/8+32) /* integer and fp regs */ -unsigned long regs[IA64_REG_COUNT]; /* integer and fp regs */ -}; -#endif #if defined(sparc) || defined(sparcv9) #define user_regs_struct pt_regs diff --git a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp index c0a1e66965e..2ee4a2a02f1 100644 --- a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp +++ b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp @@ -27,10 +27,7 @@ #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h" -#ifdef _M_IA64 - #include "sun_jvm_hotspot_debugger_ia64_IA64ThreadContext.h" - #define NPRGREG sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_NPRGREG -#elif _M_IX86 +#ifdef _M_IX86 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #elif _M_AMD64 @@ -491,92 +488,7 @@ static bool addThreads(JNIEnv* env, jobject obj) { memset(&context, 0, sizeof(CONTEXT)); #undef REG_INDEX -#ifdef _M_IA64 - #define REG_INDEX(x) sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_##x - - context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG; - ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); - - ptrRegs[REG_INDEX(GR0)] = 0; // always 0 - ptrRegs[REG_INDEX(GR1)] = context.IntGp; // r1 - ptrRegs[REG_INDEX(GR2)] = context.IntT0; // r2-r3 - ptrRegs[REG_INDEX(GR3)] = context.IntT1; - ptrRegs[REG_INDEX(GR4)] = context.IntS0; // r4-r7 - ptrRegs[REG_INDEX(GR5)] = context.IntS1; - ptrRegs[REG_INDEX(GR6)] = context.IntS2; - ptrRegs[REG_INDEX(GR7)] = context.IntS3; - ptrRegs[REG_INDEX(GR8)] = context.IntV0; // r8 - ptrRegs[REG_INDEX(GR9)] = context.IntT2; // r9-r11 - ptrRegs[REG_INDEX(GR10)] = context.IntT3; - ptrRegs[REG_INDEX(GR11)] = context.IntT4; - ptrRegs[REG_INDEX(GR12)] = context.IntSp; // r12 stack pointer - ptrRegs[REG_INDEX(GR13)] = context.IntTeb; // r13 teb - ptrRegs[REG_INDEX(GR14)] = context.IntT5; // r14-r31 - ptrRegs[REG_INDEX(GR15)] = context.IntT6; - ptrRegs[REG_INDEX(GR16)] = context.IntT7; - ptrRegs[REG_INDEX(GR17)] = context.IntT8; - ptrRegs[REG_INDEX(GR18)] = context.IntT9; - ptrRegs[REG_INDEX(GR19)] = context.IntT10; - ptrRegs[REG_INDEX(GR20)] = context.IntT11; - ptrRegs[REG_INDEX(GR21)] = context.IntT12; - ptrRegs[REG_INDEX(GR22)] = context.IntT13; - ptrRegs[REG_INDEX(GR23)] = context.IntT14; - ptrRegs[REG_INDEX(GR24)] = context.IntT15; - ptrRegs[REG_INDEX(GR25)] = context.IntT16; - ptrRegs[REG_INDEX(GR26)] = context.IntT17; - ptrRegs[REG_INDEX(GR27)] = context.IntT18; - ptrRegs[REG_INDEX(GR28)] = context.IntT19; - ptrRegs[REG_INDEX(GR29)] = context.IntT20; - ptrRegs[REG_INDEX(GR30)] = context.IntT21; - ptrRegs[REG_INDEX(GR31)] = context.IntT22; - - ptrRegs[REG_INDEX(INT_NATS)] = context.IntNats; - ptrRegs[REG_INDEX(PREDS)] = context.Preds; - - ptrRegs[REG_INDEX(BR_RP)] = context.BrRp; - ptrRegs[REG_INDEX(BR1)] = context.BrS0; // b1-b5 - ptrRegs[REG_INDEX(BR2)] = context.BrS1; - ptrRegs[REG_INDEX(BR3)] = context.BrS2; - ptrRegs[REG_INDEX(BR4)] = context.BrS3; - ptrRegs[REG_INDEX(BR5)] = context.BrS4; - ptrRegs[REG_INDEX(BR6)] = context.BrT0; // b6-b7 - ptrRegs[REG_INDEX(BR7)] = context.BrT1; - - ptrRegs[REG_INDEX(AP_UNAT)] = context.ApUNAT; - ptrRegs[REG_INDEX(AP_LC)] = context.ApLC; - ptrRegs[REG_INDEX(AP_EC)] = context.ApEC; - ptrRegs[REG_INDEX(AP_CCV)] = context.ApCCV; - ptrRegs[REG_INDEX(AP_DCR)] = context.ApDCR; - - ptrRegs[REG_INDEX(RS_PFS)] = context.RsPFS; - ptrRegs[REG_INDEX(RS_BSP)] = context.RsBSP; - ptrRegs[REG_INDEX(RS_BSPSTORE)] = context.RsBSPSTORE; - ptrRegs[REG_INDEX(RS_RSC)] = context.RsRSC; - ptrRegs[REG_INDEX(RS_RNAT)] = context.RsRNAT; - - ptrRegs[REG_INDEX(ST_IPSR)] = context.StIPSR; - ptrRegs[REG_INDEX(ST_IIP)] = context.StIIP; - ptrRegs[REG_INDEX(ST_IFS)] = context.StIFS; - - ptrRegs[REG_INDEX(DB_I0)] = context.DbI0; - ptrRegs[REG_INDEX(DB_I1)] = context.DbI1; - ptrRegs[REG_INDEX(DB_I2)] = context.DbI2; - ptrRegs[REG_INDEX(DB_I3)] = context.DbI3; - ptrRegs[REG_INDEX(DB_I4)] = context.DbI4; - ptrRegs[REG_INDEX(DB_I5)] = context.DbI5; - ptrRegs[REG_INDEX(DB_I6)] = context.DbI6; - ptrRegs[REG_INDEX(DB_I7)] = context.DbI7; - - ptrRegs[REG_INDEX(DB_D0)] = context.DbD0; - ptrRegs[REG_INDEX(DB_D1)] = context.DbD1; - ptrRegs[REG_INDEX(DB_D2)] = context.DbD2; - ptrRegs[REG_INDEX(DB_D3)] = context.DbD3; - ptrRegs[REG_INDEX(DB_D4)] = context.DbD4; - ptrRegs[REG_INDEX(DB_D5)] = context.DbD5; - ptrRegs[REG_INDEX(DB_D6)] = context.DbD6; - ptrRegs[REG_INDEX(DB_D7)] = context.DbD7; - -#elif _M_IX86 +#ifdef _M_IX86 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java index bf30dd0a5bf..ec5aea35e8c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -34,21 +34,11 @@ class WindbgAMD64Thread implements ThreadProxy { private boolean gotID; private long id; - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ + // The address argument must be the address of the OSThread::_thread_id WindbgAMD64Thread(WindbgDebugger debugger, Address addr) { this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; + this.sysId = (long)addr.getCIntegerAt(0, 4, true); + gotID = false; } WindbgAMD64Thread(WindbgDebugger debugger, long sysId) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java index 84d19e03bc0..e5417972b13 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -34,21 +34,11 @@ class WindbgX86Thread implements ThreadProxy { private boolean gotID; private long id; - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ + // The address argument must be the address of OSThread::_thread_id WindbgX86Thread(WindbgDebugger debugger, Address addr) { this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; + this.sysId = (long)addr.getCIntegerAt(0, 4, true); + gotID = false; } WindbgX86Thread(WindbgDebugger debugger, long sysId) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java similarity index 85% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java index 802af91bbc7..5b56cf5f815 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java @@ -1,6 +1,6 @@ /* * @(#)BinaryTreeDictionary.java - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -30,7 +30,7 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.runtime.*; -public class BinaryTreeDictionary extends VMObject { +public class AFLBinaryTreeDictionary extends VMObject { static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -40,8 +40,8 @@ public class BinaryTreeDictionary extends VMObject { } private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("BinaryTreeDictionary"); - totalSizeField = type.getCIntegerField("_totalSize"); + Type type = db.lookupType("AFLBinaryTreeDictionary"); + totalSizeField = type.getCIntegerField("_total_size"); } // Fields @@ -53,7 +53,7 @@ public class BinaryTreeDictionary extends VMObject { } // Constructor - public BinaryTreeDictionary(Address addr) { + public AFLBinaryTreeDictionary(Address addr) { super(addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java index c2e8200b694..f47f0e81127 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,9 +117,9 @@ public class CompactibleFreeListSpace extends CompactibleSpace { } // large block - BinaryTreeDictionary bfbd = (BinaryTreeDictionary) VMObjectFactory.newObject(BinaryTreeDictionary.class, + AFLBinaryTreeDictionary aflbd = (AFLBinaryTreeDictionary) VMObjectFactory.newObject(AFLBinaryTreeDictionary.class, dictionaryField.getValue(addr)); - size += bfbd.size(); + size += aflbd.size(); // linear block in TLAB diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java index 23d7c3d34ee..2d0024e1d2d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java @@ -1,7 +1,7 @@ /* * @(#)FreeList.java * - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -41,7 +41,7 @@ public class FreeList extends VMObject { } private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("FreeList"); + Type type = db.lookupType("FreeList"); sizeField = type.getCIntegerField("_size"); countField = type.getCIntegerField("_count"); headerSize = type.getSize(); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index ba07fa34800..cfa26eacdbd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -52,6 +52,9 @@ public class InstanceKlass extends Klass { private static int LOW_OFFSET; private static int HIGH_OFFSET; private static int FIELD_SLOTS; + private static short FIELDINFO_TAG_SIZE; + private static short FIELDINFO_TAG_MASK; + private static short FIELDINFO_TAG_OFFSET; // ClassState constants private static int CLASS_STATE_ALLOCATED; @@ -96,9 +99,13 @@ public class InstanceKlass extends Klass { NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue(); SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue(); INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue(); - LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue(); - HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue(); + LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue(); + HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue(); FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue(); + FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue(); + FIELDINFO_TAG_MASK = db.lookupIntConstant("FIELDINFO_TAG_MASK").shortValue(); + FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue(); + // read ClassState constants CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue(); CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue(); @@ -314,8 +321,12 @@ public class InstanceKlass extends Klass { public int getFieldOffset(int index) { U2Array fields = getFields(); - return VM.getVM().buildIntFromShorts(fields.at(index * FIELD_SLOTS + LOW_OFFSET), - fields.at(index * FIELD_SLOTS + HIGH_OFFSET)); + short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET); + short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET); + if ((lo & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET) { + return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE; + } + throw new RuntimeException("should not reach here"); } // Accessors for declared fields diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java index 59923078d3d..f944188f4d1 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java @@ -467,7 +467,7 @@ public class ObjectHeap { liveRegions.add(tlab.start()); liveRegions.add(tlab.start()); liveRegions.add(tlab.top()); - liveRegions.add(tlab.end()); + liveRegions.add(tlab.hardEnd()); } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java index cdcbf113871..fb17c53d329 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -32,6 +32,7 @@ import sun.jvm.hotspot.types.*; // to the sys_thread_t structure of the classic JVM implementation. public class OSThread extends VMObject { private static JIntField interruptedField; + private static JIntField threadIdField; static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -43,6 +44,7 @@ public class OSThread extends VMObject { private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("OSThread"); interruptedField = type.getJIntField("_interrupted"); + threadIdField = type.getJIntField("_thread_id"); } public OSThread(Address addr) { @@ -52,4 +54,9 @@ public class OSThread extends VMObject { public boolean interrupted() { return ((int)interruptedField.getValue(addr)) != 0; } + + public int threadId() { + return (int)threadIdField.getValue(addr); + } + } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java index 381b53deded..738dc94fa91 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java @@ -27,6 +27,7 @@ package sun.jvm.hotspot.runtime; import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; /**

ThreadLocalAllocBuffer: a descriptor for thread-local storage @@ -62,9 +63,22 @@ public class ThreadLocalAllocBuffer extends VMObject { super(addr); } - public Address start() { return startField.getValue(addr); } - public Address end() { return endField.getValue(addr); } - public Address top() { return topField.getValue(addr); } + public Address start() { return startField.getValue(addr); } + public Address end() { return endField.getValue(addr); } + public Address top() { return topField.getValue(addr); } + public Address hardEnd() { return end().addOffsetTo(alignmentReserve()); } + + private long alignmentReserve() { + return Oop.alignObjectSize(endReserve()); + } + + private long endReserve() { + long minFillerArraySize = Array.baseOffsetInBytes(BasicType.T_INT); + long reserveForAllocationPrefetch = VM.getVM().getReserveForAllocationPrefetch(); + long heapWordSize = VM.getVM().getHeapWordSize(); + + return Math.max(minFillerArraySize, reserveForAllocationPrefetch * heapWordSize); + } /** Support for iteration over heap -- not sure how this will interact with GC in reflective system, but necessary for the diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 5531980b1f8..80464a10bb0 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -114,6 +114,7 @@ public class VM { private int invalidOSREntryBCI; private ReversePtrs revPtrs; private VMRegImpl vmregImpl; + private int reserveForAllocationPrefetch; // System.getProperties from debuggee VM private Properties sysProps; @@ -293,6 +294,10 @@ public class VM { vmRelease = CStringUtilities.getString(releaseAddr); Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue(); vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr); + + CIntegerType intType = (CIntegerType) db.lookupType("int"); + CIntegerField reserveForAllocationPrefetchField = vmVersion.getCIntegerField("_reserve_for_allocation_prefetch"); + reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType); } catch (Exception exp) { throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); } @@ -778,6 +783,10 @@ public class VM { return vmInternalInfo; } + public int getReserveForAllocationPrefetch() { + return reserveForAllocationPrefetch; + } + public boolean isSharingEnabled() { if (sharingEnabled == null) { Flag flag = getCommandLineFlag("UseSharedSpaces"); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java index e18dd4f8053..86255a48f6e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -43,7 +43,7 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { private static AddressField osThreadField; // Field from OSThread - private static Field osThreadThreadHandleField; + private static Field osThreadThreadIdField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -64,7 +64,7 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { osThreadField = type.getAddressField("_osthread"); type = db.lookupType("OSThread"); - osThreadThreadHandleField = type.getField("_thread_handle"); + osThreadThreadIdField = type.getField("_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -128,10 +128,10 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); - // Get the address of the HANDLE within the OSThread - Address threadHandleAddr = - osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset()); + // Get the address of the thread_id within the OSThread + Address threadIdAddr = + osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadHandleAddr); + return debugger.getThreadForIdentifierAddress(threadIdAddr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java index dff6615a008..435e4762335 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -42,7 +42,7 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { private static AddressField osThreadField; // Field from OSThread - private static Field osThreadThreadHandleField; + private static Field osThreadThreadIdField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -63,7 +63,7 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { osThreadField = type.getAddressField("_osthread"); type = db.lookupType("OSThread"); - osThreadThreadHandleField = type.getField("_thread_handle"); + osThreadThreadIdField = type.getField("_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -127,10 +127,10 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); - // Get the address of the HANDLE within the OSThread - Address threadHandleAddr = - osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset()); + // Get the address of the thread_id within the OSThread + Address threadIdAddr = + osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadHandleAddr); + return debugger.getThreadForIdentifierAddress(threadIdAddr); } } diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index fe5a6b684d6..a1d8cb9dde6 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -87,7 +87,6 @@ endif # Typical C1/C2 targets made available with this Makefile C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1 C2_VM_TARGETS=product fastdebug optimized jvmg -KERNEL_VM_TARGETS=productkernel fastdebugkernel optimizedkernel jvmgkernel ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero jvmgzero SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark jvmgshark MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 jvmgminimal1 @@ -161,11 +160,6 @@ $(C2_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT) -$(KERNEL_VM_TARGETS): - $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$(@:%kernel=%) VM_TARGET=$@ \ - generic_buildkernel $(ALT_OUT) - $(ZERO_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ \ @@ -223,24 +217,6 @@ else $(MAKE_ARGS) $(VM_TARGET) endif -generic_buildkernel: - $(MKDIR) -p $(OUTPUTDIR) -ifeq ($(OSNAME),windows) - ifeq ($(ARCH_DATA_MODEL), 32) - $(CD) $(OUTPUTDIR); \ - $(NMAKE) -f $(ABS_OS_MAKEFILE) \ - Variant=kernel \ - WorkSpace=$(ABS_GAMMADIR) \ - BootStrapDir=$(ABS_BOOTDIR) \ - BuildUser=$(USERNAME) \ - $(MAKE_ARGS) $(VM_TARGET:%kernel=%) - else - @$(ECHO) "No kernel ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" - endif -else - @$(ECHO) "No kernel ($(VM_TARGET)) for OS_NAME=$(OSNAME)" -endif - generic_buildzero: $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ @@ -314,12 +290,10 @@ XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs C1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1 C2_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2 -KERNEL_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_kernel ZERO_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_zero SHARK_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_shark C1_DIR=$(C1_BASE_DIR)/$(VM_SUBDIR) C2_DIR=$(C2_BASE_DIR)/$(VM_SUBDIR) -KERNEL_DIR=$(KERNEL_BASE_DIR)/$(VM_SUBDIR) ZERO_DIR=$(ZERO_BASE_DIR)/$(VM_SUBDIR) SHARK_DIR=$(SHARK_BASE_DIR)/$(VM_SUBDIR) MINIMAL1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1 @@ -333,10 +307,6 @@ ifeq ($(JVM_VARIANT_CLIENT), true) MISC_DIR=$(C1_DIR) GEN_DIR=$(C1_BASE_DIR)/generated endif -ifeq ($(JVM_VARIANT_KERNEL), true) - MISC_DIR=$(C2_DIR) - GEN_DIR=$(C2_BASE_DIR)/generated -endif ifeq ($(JVM_VARIANT_ZEROSHARK), true) MISC_DIR=$(SHARK_DIR) GEN_DIR=$(SHARK_BASE_DIR)/generated @@ -386,16 +356,6 @@ $(EXPORT_SERVER_DIR)/%.pdb: $(C2_DIR)/%.pdb $(install-file) $(EXPORT_SERVER_DIR)/%.map: $(C2_DIR)/%.map $(install-file) - -# Kernel files always come from kernel area -$(EXPORT_KERNEL_DIR)/%.diz: $(KERNEL_DIR)/%.diz - $(install-file) -$(EXPORT_KERNEL_DIR)/%.dll: $(KERNEL_DIR)/%.dll - $(install-file) -$(EXPORT_KERNEL_DIR)/%.pdb: $(KERNEL_DIR)/%.pdb - $(install-file) -$(EXPORT_KERNEL_DIR)/%.map: $(KERNEL_DIR)/%.map - $(install-file) endif # Minimal JVM files always come from minimal area @@ -538,7 +498,7 @@ $(EXPORT_DOCS_DIR)/platform/jvmti/%: $(DOCS_DIR)/% $(install-file) # Xusage file -$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_KERNEL_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE) +$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE) $(prep-target) $(RM) $@.temp $(SED) 's/\(separated by \)[;:]/\1$(PATH_SEP)/g' $< > $@.temp @@ -551,7 +511,6 @@ clobber clean: clean_build clean_export clean_jdk clean_build: $(RM) -r $(C1_DIR) $(RM) -r $(C2_DIR) - $(RM) -r $(KERNEL_DIR) $(RM) -r $(ZERO_DIR) $(RM) -r $(SHARK_DIR) $(RM) -r $(MINIMAL1_DIR) @@ -586,10 +545,6 @@ test_jdk: $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -Xinternalversion $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -version endif - ifeq ($(JVM_VARIANT_KERNEL), true) - $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -Xinternalversion - $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -version - endif copy_product_jdk:: $(RM) -r $(JDK_IMAGE_DIR) @@ -665,7 +620,6 @@ target_help: @$(ECHO) "Other targets are:" @$(ECHO) " $(C1_VM_TARGETS)" @$(ECHO) " $(C2_VM_TARGETS)" - @$(ECHO) " $(KERNEL_VM_TARGETS)" @$(ECHO) " $(MINIMAL1_VM_TARGETS)" # Variable help (only common ones used by this workspace) @@ -761,8 +715,8 @@ endif include $(GAMMADIR)/make/jprt.gmk .PHONY: all world clobber clean help $(C1_VM_TARGETS) $(C2_VM_TARGETS) \ - $(KERNEL_VM_TARGETS) $(MINIMAL1_VM_TARGETS) \ - generic_build1 generic_build2 generic_buildkernel generic_buildminimal1 generic_export \ + $(MINIMAL1_VM_TARGETS) \ + generic_build1 generic_build2 generic_buildminimal1 generic_export \ export_product export_fastdebug export_debug export_optimized \ export_jdk_product export_jdk_fastdebug export_jdk_debug \ create_jdk copy_jdk update_jdk test_jdk \ diff --git a/hotspot/make/bsd/makefiles/dtrace.make b/hotspot/make/bsd/makefiles/dtrace.make index d325f2082dd..1c53841b56c 100644 --- a/hotspot/make/bsd/makefiles/dtrace.make +++ b/hotspot/make/bsd/makefiles/dtrace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -25,10 +25,9 @@ # Rules to build jvm_db/dtrace, used by vm.make # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE or KERNEL configurations. +# but not for CORE configuration. ifneq ("${TYPE}", "CORE") -ifneq ("${TYPE}", "KERNEL") ifeq ($(OS_VENDOR), Darwin) # we build dtrace for macosx using USDT2 probes @@ -280,13 +279,6 @@ endif # ifneq ("${dtraceFound}", "") endif # ifeq ($(OS_VENDOR), Darwin) -else # KERNEL build - -dtraceCheck: - $(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds" - -endif # ifneq ("${TYPE}", "KERNEL") - else # CORE build dtraceCheck: diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug index 00fd1892716..24144fe9b70 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug @@ -3,7 +3,7 @@ # # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 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 @@ -188,6 +188,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; @@ -205,7 +206,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product index dfa459f0316..c165c16e2d8 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product @@ -3,7 +3,7 @@ # # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 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 @@ -188,6 +188,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; @@ -205,7 +206,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/bsd/makefiles/minimal1.make b/hotspot/make/bsd/makefiles/minimal1.make index 9494f78bcdd..abfbc4c9490 100644 --- a/hotspot/make/bsd/makefiles/minimal1.make +++ b/hotspot/make/bsd/makefiles/minimal1.make @@ -30,7 +30,7 @@ INCLUDE_VM_STRUCTS ?= false INCLUDE_JNI_CHECK ?= false INCLUDE_SERVICES ?= false INCLUDE_MANAGEMENT ?= false -INCLUDE_ALTERNATE_GCS ?= false +INCLUDE_ALL_GCS ?= false INCLUDE_NMT ?= false INCLUDE_CDS ?= false diff --git a/hotspot/make/excludeSrc.make b/hotspot/make/excludeSrc.make index 721aea5c7e5..589c262ca3c 100644 --- a/hotspot/make/excludeSrc.make +++ b/hotspot/make/excludeSrc.make @@ -72,12 +72,10 @@ ifeq ($(INCLUDE_CDS), false) Src_Files_EXCLUDE += metaspaceShared.cpp endif -ifeq ($(INCLUDE_ALTERNATE_GCS), false) - CXXFLAGS += -DINCLUDE_ALTERNATE_GCS=0 - CFLAGS += -DINCLUDE_ALTERNATE_GCS=0 +ifeq ($(INCLUDE_ALL_GCS), false) + CXXFLAGS += -DINCLUDE_ALL_GCS=0 + CFLAGS += -DINCLUDE_ALL_GCS=0 - CXXFLAGS += -DSERIALGC - CFLAGS += -DSERIALGC Src_Files_EXCLUDE += \ cmsAdaptiveSizePolicy.cpp cmsCollectorPolicy.cpp \ cmsGCAdaptivePolicyCounters.cpp cmsLockVerifier.cpp cmsPermGen.cpp compactibleFreeListSpace.cpp \ diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index d6959b3b86c..6f09485a3a3 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -31,11 +31,11 @@ # # Don't put quotes (fail windows build). -HOTSPOT_VM_COPYRIGHT=Copyright 2012 +HOTSPOT_VM_COPYRIGHT=Copyright 2013 HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=15 +HS_BUILD_NUMBER=18 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index d6ebedcb9bd..27238f5720a 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 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 @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; @@ -201,7 +202,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 733e3af4b11..04531fa15aa 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 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 @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; @@ -201,7 +202,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/linux/makefiles/minimal1.make b/hotspot/make/linux/makefiles/minimal1.make index 9494f78bcdd..abfbc4c9490 100644 --- a/hotspot/make/linux/makefiles/minimal1.make +++ b/hotspot/make/linux/makefiles/minimal1.make @@ -30,7 +30,7 @@ INCLUDE_VM_STRUCTS ?= false INCLUDE_JNI_CHECK ?= false INCLUDE_SERVICES ?= false INCLUDE_MANAGEMENT ?= false -INCLUDE_ALTERNATE_GCS ?= false +INCLUDE_ALL_GCS ?= false INCLUDE_NMT ?= false INCLUDE_CDS ?= false diff --git a/hotspot/make/solaris/Makefile b/hotspot/make/solaris/Makefile index 4a47cb93716..83e4df66579 100644 --- a/hotspot/make/solaris/Makefile +++ b/hotspot/make/solaris/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 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 @@ -157,13 +157,11 @@ SUBDIRS_C1 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler1/,$(TARGETS)) SUBDIRS_C2 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS)) SUBDIRS_TIERED = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS)) SUBDIRS_CORE = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS)) -SUBDIRS_KERNEL = $(addprefix $(OSNAME)_$(BUILDARCH)_kernel/,$(TARGETS)) TARGETS_C2 = $(TARGETS) TARGETS_C1 = $(addsuffix 1,$(TARGETS)) TARGETS_TIERED = $(addsuffix tiered,$(TARGETS)) TARGETS_CORE = $(addsuffix core,$(TARGETS)) -TARGETS_KERNEL = $(addsuffix kernel,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) @@ -229,10 +227,6 @@ $(SUBDIRS_CORE): $(BUILDTREE_MAKE) $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=core -$(SUBDIRS_KERNEL): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks - $(BUILDTREE) VARIANT=kernel - # Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME $(TARGETS_C2): $(SUBDIRS_C2) @@ -271,20 +265,10 @@ ifdef INSTALL cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install endif -$(TARGETS_KERNEL): $(SUBDIRS_KERNEL) - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) -ifeq ($(TEST_IN_BUILD),true) - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && ./test_gamma -endif -ifdef INSTALL - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) install -endif - # Just build the tree, and nothing else: tree: $(SUBDIRS_C2) tree1: $(SUBDIRS_C1) treecore: $(SUBDIRS_CORE) -treekernel: $(SUBDIRS_KERNEL) # Doc target. This is the same for all build options. # Hence create a docs directory beside ...$(ARCH)_[...] @@ -304,10 +288,10 @@ core: jvmgcore productcore clean_docs: rm -rf $(SUBDIR_DOCS) -clean_compiler1 clean_compiler2 clean_core clean_kernel: +clean_compiler1 clean_compiler2 clean_core: rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@) -clean: clean_compiler2 clean_compiler1 clean_core clean_docs clean_kernel +clean: clean_compiler2 clean_compiler1 clean_core clean_docs include $(GAMMADIR)/make/cscope.make diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make index 111acdb0d96..b57365b93dc 100644 --- a/hotspot/make/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -25,10 +25,9 @@ # Rules to build jvm_db/dtrace, used by vm.make # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE or KERNEL configurations. +# but not for CORE configuration. ifneq ("${TYPE}", "CORE") -ifneq ("${TYPE}", "KERNEL") ifdef USE_GCC @@ -362,13 +361,6 @@ endif # ifneq ("${dtraceFound}", "") endif # ifdef USE_GCC -else # KERNEL build - -dtraceCheck: - $(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds" - -endif # ifneq ("${TYPE}", "KERNEL") - else # CORE build dtraceCheck: diff --git a/hotspot/make/solaris/makefiles/kernel.make b/hotspot/make/solaris/makefiles/kernel.make deleted file mode 100644 index 40728e669f1..00000000000 --- a/hotspot/make/solaris/makefiles/kernel.make +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# -# -# Sets make macros for making kernel version of VM. -# This target on solaris is just tempoarily for debugging the kernel build. - -TYPE=KERNEL - -VM_SUBDIR = client - -CFLAGS += -DKERNEL diff --git a/hotspot/make/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers index a10d5c1b4e6..d58807b046d 100644 --- a/hotspot/make/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 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 @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; @@ -201,7 +202,6 @@ SUNWprivate_1.1 { JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff --git a/hotspot/make/windows/build.bat b/hotspot/make/windows/build.bat index e4eab3abf0c..5df20dd4f1e 100644 --- a/hotspot/make/windows/build.bat +++ b/hotspot/make/windows/build.bat @@ -1,6 +1,6 @@ @echo off REM -REM Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +REM Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. REM REM This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,6 @@ goto usage :test1 if "%2" == "core" goto test2 -if "%2" == "kernel" goto test2 if "%2" == "compiler1" goto test2 if "%2" == "compiler2" goto test2 if "%2" == "tiered" goto test2 @@ -109,7 +108,7 @@ echo Usage: build flavor version workspace bootstrap_dir [build_id] [windbg_home echo. echo where: echo flavor is "product", "debug" or "fastdebug", -echo version is "core", "kernel", "compiler1", "compiler2", or "tiered", +echo version is "core", "compiler1", "compiler2", or "tiered", echo workspace is source directory without trailing slash, echo bootstrap_dir is a full path to a JDK in which bin/java echo and bin/javac are present and working, and build_id is an diff --git a/hotspot/make/windows/create_obj_files.sh b/hotspot/make/windows/create_obj_files.sh index 78fabc06ddc..14a7087f2aa 100644 --- a/hotspot/make/windows/create_obj_files.sh +++ b/hotspot/make/windows/create_obj_files.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -107,7 +107,6 @@ COMPILER2_PATHS="${COMPILER2_PATHS} ${GENERATED}/adfiles" # Include dirs per type. case "${TYPE}" in "core") Src_Dirs="${CORE_PATHS}" ;; - "kernel") Src_Dirs="${BASE_PATHS} ${COMPILER1_PATHS}" ;; "compiler1") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS}" ;; "compiler2") Src_Dirs="${CORE_PATHS} ${COMPILER2_PATHS}" ;; "tiered") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS} ${COMPILER2_PATHS}" ;; @@ -120,16 +119,12 @@ COMPILER1_SPECIFIC_FILES="c1_*" SHARK_SPECIFIC_FILES="shark" ZERO_SPECIFIC_FILES="zero" -# These files need to be excluded when building the kernel target. -KERNEL_EXCLUDED_FILES="attachListener.cpp attachListener_windows.cpp metaspaceShared_${Platform_arch_model}.cpp forte.cpp fprofiler.cpp heapDumper.cpp heapInspection.cpp jniCheck.cpp jvmtiCodeBlobEvents.cpp jvmtiExtensions.cpp jvmtiImpl.cpp jvmtiRawMonitor.cpp jvmtiTagMap.cpp jvmtiTrace.cpp vmStructs.cpp g1MemoryPool.cpp psMemoryPool.cpp gcAdaptivePolicyCounters.cpp concurrentGCThread.cpp metaspaceShared.cpp mutableNUMASpace.cpp allocationStats.cpp gSpaceCounters.cpp immutableSpace.cpp mutableSpace.cpp spaceCounters.cpp yieldingWorkgroup.cpp" - # Always exclude these. Src_Files_EXCLUDE="jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp" # Exclude per type. case "${TYPE}" in "core") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;; - "kernel") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ${KERNEL_EXCLUDED_FILES} ciTypeFlow.cpp" ;; "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;; "compiler2") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;; "tiered") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;; diff --git a/hotspot/make/windows/makefiles/defs.make b/hotspot/make/windows/makefiles/defs.make index e637c00335d..5d58e699bf2 100644 --- a/hotspot/make/windows/makefiles/defs.make +++ b/hotspot/make/windows/makefiles/defs.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -157,7 +157,7 @@ endif MAKE_ARGS += RM="$(RM)" MAKE_ARGS += ZIPEXE=$(ZIPEXE) -# On 32 bit windows we build server, client and kernel, on 64 bit just server. +# On 32 bit windows we build server and client, on 64 bit just server. ifeq ($(JVM_VARIANTS),) ifeq ($(ARCH_DATA_MODEL), 32) JVM_VARIANTS:=client,server @@ -250,7 +250,6 @@ endif EXPORT_SERVER_DIR = $(EXPORT_JRE_BIN_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_BIN_DIR)/client -EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel ifeq ($(JVM_VARIANT_SERVER),true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt @@ -277,18 +276,6 @@ ifeq ($(JVM_VARIANT_CLIENT),true) endif endif endif -ifeq ($(JVM_VARIANT_KERNEL),true) - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX) - ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) - ifeq ($(ZIP_DEBUGINFO_FILES),1) - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.diz - else - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map - endif - endif -endif EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar diff --git a/hotspot/make/windows/makefiles/projectcreator.make b/hotspot/make/windows/makefiles/projectcreator.make index 5d71de6618a..68d098d0de3 100644 --- a/hotspot/make/windows/makefiles/projectcreator.make +++ b/hotspot/make/windows/makefiles/projectcreator.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -166,63 +166,6 @@ ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=core) \ $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=core) -################################################## -# JKERNEL specific options -################################################## -ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ - -define_kernel KERNEL \ -$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=kernel) \ - -ignorePath_kernel src/share/vm/gc_implementation/parallelScavenge \ - -ignorePath_kernel src/share/vm/gc_implementation/parNew \ - -ignorePath_kernel src/share/vm/gc_implementation/concurrentMarkSweep \ - -ignorePath_kernel src/share/vm/gc_implementation/g1 \ - -ignoreFile_kernel attachListener.cpp \ - -ignoreFile_kernel attachListener_windows.cpp \ - -ignoreFile_kernel dump.cpp \ - -ignoreFile_kernel dump_$(Platform_arch_model).cpp \ - -ignoreFile_kernel forte.cpp \ - -ignoreFile_kernel fprofiler.cpp \ - -ignoreFile_kernel heapDumper.cpp \ - -ignoreFile_kernel heapInspection.cpp \ - -ignoreFile_kernel jniCheck.cpp \ - -ignoreFile_kernel jvmtiCodeBlobEvents.cpp \ - -ignoreFile_kernel jvmtiExtensions.cpp \ - -ignoreFile_kernel jvmtiImpl.cpp \ - -ignoreFile_kernel jvmtiRawMonitor.cpp \ - -ignoreFile_kernel jvmtiTagMap.cpp \ - -ignoreFile_kernel jvmtiTrace.cpp \ - -ignoreFile_kernel jvmtiTrace.hpp \ - -ignoreFile_kernel restore.cpp \ - -ignoreFile_kernel serialize.cpp \ - -ignoreFile_kernel vmStructs.cpp \ - -ignoreFile_kernel g1MemoryPool.cpp \ - -ignoreFile_kernel g1MemoryPool.hpp \ - -ignoreFile_kernel psMemoryPool.cpp \ - -ignoreFile_kernel psMemoryPool.hpp \ - -ignoreFile_kernel gcAdaptivePolicyCounters.cpp \ - -ignoreFile_kernel concurrentGCThread.cpp \ - -ignoreFile_kernel mutableNUMASpace.cpp \ - -ignoreFile_kernel ciTypeFlow.cpp \ - -ignoreFile_kernel ciTypeFlow.hpp \ - -ignoreFile_kernel oop.pcgc.inline.hpp \ - -ignoreFile_kernel oop.psgc.inline.hpp \ - -ignoreFile_kernel allocationStats.cpp \ - -ignoreFile_kernel allocationStats.hpp \ - -ignoreFile_kernel concurrentGCThread.hpp \ - -ignoreFile_kernel gSpaceCounters.cpp \ - -ignoreFile_kernel gSpaceCounters.hpp \ - -ignoreFile_kernel gcAdaptivePolicyCounters.hpp \ - -ignoreFile_kernel immutableSpace.cpp \ - -ignoreFile_kernel mutableNUMASpace.hpp \ - -ignoreFile_kernel mutableSpace.cpp \ - -ignoreFile_kernel spaceCounters.cpp \ - -ignoreFile_kernel spaceCounters.hpp \ - -ignoreFile_kernel yieldingWorkgroup.cpp \ - -ignoreFile_kernel yieldingWorkgroup.hpp \ - -ignorePath_kernel vmStructs_ \ - -ignoreFile_kernel $(Platform_arch_model).ad \ - -additionalFile_kernel gcTaskManager.hpp - ################################################## # Client(C1) compiler specific options ################################################## diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make index b1e71de0e5a..2e501a7b9f7 100644 --- a/hotspot/make/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -44,10 +44,6 @@ CXX_FLAGS=$(CXX_FLAGS) /D "ASSERT" # No need to define anything, CORE is defined as !COMPILER1 && !COMPILER2 !endif -!if "$(Variant)" == "kernel" -CXX_FLAGS=$(CXX_FLAGS) /D "KERNEL" -!endif - !if "$(Variant)" == "compiler1" CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" !endif diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp index fa5ce4fa6be..6d936b376e0 100644 --- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp @@ -30,10 +30,11 @@ #include "c1/c1_Runtime1.hpp" #include "nativeInst_sparc.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" #include "vmreg_sparc.inline.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define __ ce->masm()-> @@ -420,7 +421,7 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) { /////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { // At this point we know that marking is in progress. @@ -483,7 +484,7 @@ void G1PostBarrierStub::emit_code(LIR_Assembler* ce) { __ delayed()->nop(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS /////////////////////////////////////////////////////////////////////////////////// #undef __ diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 017baa61d0a..b8c838b1620 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/macros.hpp" #include "vmreg_sparc.inline.hpp" // Implementation of StubAssembler @@ -822,7 +823,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case g1_pre_barrier_slow_id: { // G4: previous value of memory BarrierSet* bs = Universe::heap()->barrier_set(); @@ -984,7 +985,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ delayed()->restore(); } break; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS default: { __ set_info("unimplemented entry", dont_gc_arguments); diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp index 0dcdea0567b..c642e915fe1 100644 --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp @@ -42,7 +42,7 @@ define_pd_global(bool, ProfileInterpreter, false); #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 140000); diff --git a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp index 6066c2019d5..4918746db13 100644 --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp @@ -45,6 +45,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -551,7 +552,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -563,7 +564,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index 3690a9272e4..251e42cd6af 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -3867,7 +3868,7 @@ void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp, } /////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS static address satb_log_enqueue_with_frame = NULL; static u_char* satb_log_enqueue_with_frame_end = NULL; @@ -4231,7 +4232,7 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val bind(filtered); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS /////////////////////////////////////////////////////////////////////////////////// void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) { diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp index dffef7e794b..26605cbfa4c 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp @@ -26,6 +26,7 @@ #define CPU_SPARC_VM_MACROASSEMBLER_SPARC_HPP #include "asm/assembler.hpp" +#include "utilities/macros.hpp" // promises that the system will not use traps 16-31 #define ST_RESERVED_FOR_USER_0 0x10 @@ -1181,13 +1182,13 @@ public: void card_write_barrier_post(Register store_addr, Register new_val, Register tmp); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // General G1 pre-barrier generator. void g1_write_barrier_pre(Register obj, Register index, int offset, Register pre_val, Register tmp, bool preserve_o_regs); // General G1 post-barrier generator void g1_write_barrier_post(Register store_addr, Register new_val, Register tmp); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack void push_fTOS(); diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index ed46aa9cdc4..b5cfa00f975 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -44,6 +44,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #ifndef FAST_DISPATCH @@ -734,7 +735,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -805,7 +806,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { (void) generate_normal_entry(false); return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 931342ded12..d32a2493cfb 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -34,6 +34,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #define __ _masm-> @@ -53,7 +54,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, assert(tmp != val && tmp != base && tmp != index, "register collision"); assert(index == noreg || offset == 0, "only one offset"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -82,7 +83,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, } } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { diff --git a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp index 8103a6395b7..11f829385b8 100644 --- a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp @@ -29,7 +29,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* JavaCallWrapper */ \ @@ -37,22 +37,12 @@ /******************************/ \ /* JavaFrameAnchor */ \ /******************************/ \ - volatile_nonstatic_field(JavaFrameAnchor, _flags, int) \ - \ + volatile_nonstatic_field(JavaFrameAnchor, _flags, int) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ - /* be present there) */ - - -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ /******************************/ \ /* Register numbers (C2 only) */ \ /******************************/ \ @@ -90,15 +80,6 @@ declare_c2_constant(R_G6_num) \ declare_c2_constant(R_G7_num) - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ - -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // CPU_SPARC_VM_VMSTRUCTS_SPARC_HPP diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 7d3becef336..03670106924 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -259,6 +259,10 @@ void VM_Version::initialize() { if (!has_vis1()) // Drop to 0 if no VIS1 support UseVIS = 0; + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && + (cache_line_size > ContendedPaddingWidth)) + ContendedPaddingWidth = cache_line_size; + #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print("Allocation"); @@ -286,6 +290,9 @@ void VM_Version::initialize() { if (PrefetchFieldsAhead > 0) { tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead); } + if (ContendedPaddingWidth > 0) { + tty->print_cr("ContendedPaddingWidth %d", ContendedPaddingWidth); + } } #endif // PRODUCT } diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 8b474ba2409..b94aaa9368c 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -2263,6 +2264,18 @@ void Assembler::packuswb(XMMRegister dst, XMMRegister src) { emit_simd_arith(0x67, dst, src, VEX_SIMD_66); } +void Assembler::vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0x67, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256) { + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256); + emit_int8(0x00); + emit_int8(0xC0 | encode); + emit_int8(imm8); +} + void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); InstructionMark im(this); @@ -2475,7 +2488,7 @@ void Assembler::vptest(XMMRegister dst, Address src) { 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, vector256); + vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256); emit_int8(0x17); emit_operand(dst, src); } diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index bcef330e4cf..97a5bfc0368 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -543,7 +543,7 @@ class Assembler : public AbstractAssembler { // of instructions are freely declared without the need for wrapping them an ifdef. // (Some dangerous instructions are ifdef's out of inappropriate jvm's.) // In the .cpp file the implementations are wrapped so that they are dropped out - // of the resulting jvm. This is done mostly to keep the footprint of KERNEL + // of the resulting jvm. This is done mostly to keep the footprint of MINIMAL // to the size it was prior to merging up the 32bit and 64bit assemblers. // // This does mean you'll get a linker/runtime error if you use a 64bit only instruction @@ -1395,6 +1395,10 @@ private: // Pack with unsigned saturation void packuswb(XMMRegister dst, XMMRegister src); void packuswb(XMMRegister dst, Address src); + void vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + + // Pemutation of 64bit words + void vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256); // SSE4.2 string instructions void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); diff --git a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp index 53c7cbacd1c..806bce01bfa 100644 --- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp @@ -30,10 +30,11 @@ #include "c1/c1_Runtime1.hpp" #include "nativeInst_x86.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" #include "vmreg_x86.inline.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define __ ce->masm()-> @@ -482,7 +483,7 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) { } ///////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { // At this point we know that marking is in progress. @@ -528,7 +529,7 @@ void G1PostBarrierStub::emit_code(LIR_Assembler* ce) { __ jmp(_continuation); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ///////////////////////////////////////////////////////////////////////////// #undef __ diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index e02d5f6af7f..d3ac75e4013 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -36,6 +36,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/macros.hpp" #include "vmreg_x86.inline.hpp" @@ -1607,7 +1608,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case g1_pre_barrier_slow_id: { StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments); @@ -1804,7 +1805,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS default: { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); diff --git a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp index 5ad08b0f158..f63b8c46d58 100644 --- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp @@ -44,7 +44,7 @@ define_pd_global(bool, ProfileInterpreter, false); #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 100000); diff --git a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp index 9c3a2f31aeb..55b29fb2f6c 100644 --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp @@ -45,6 +45,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -938,7 +939,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -950,7 +951,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/x86/vm/jni_x86.h b/hotspot/src/cpu/x86/vm/jni_x86.h index d724c86007a..2cd7abd304e 100644 --- a/hotspot/src/cpu/x86/vm/jni_x86.h +++ b/hotspot/src/cpu/x86/vm/jni_x86.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,14 +38,9 @@ #define JNICALL typedef int jint; -#if defined(_LP64) && !defined(__APPLE__) +#if defined(_LP64) typedef long jlong; #else - /* - * On _LP64 __APPLE__ "long" and "long long" are both 64 bits, - * but we use the "long long" typedef to avoid complaints from - * the __APPLE__ compiler about fprintf formats. - */ typedef long long jlong; #endif diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index e9e414077f5..c1e4c96e610 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -37,11 +37,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -3207,7 +3208,7 @@ void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src ////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void MacroAssembler::g1_write_barrier_pre(Register obj, Register pre_val, @@ -3417,7 +3418,7 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, bind(done); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ////////////////////////////////////////////////////////////////////////////////// @@ -6209,6 +6210,128 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned, } BIND(L_exit); } + +// encode char[] to byte[] in ISO_8859_1 +void MacroAssembler::encode_iso_array(Register src, Register dst, Register len, + XMMRegister tmp1Reg, XMMRegister tmp2Reg, + XMMRegister tmp3Reg, XMMRegister tmp4Reg, + Register tmp5, Register result) { + // rsi: src + // rdi: dst + // rdx: len + // rcx: tmp5 + // rax: result + ShortBranchVerifier sbv(this); + assert_different_registers(src, dst, len, tmp5, result); + Label L_done, L_copy_1_char, L_copy_1_char_exit; + + // set result + xorl(result, result); + // check for zero length + testl(len, len); + jcc(Assembler::zero, L_done); + movl(result, len); + + // Setup pointers + lea(src, Address(src, len, Address::times_2)); // char[] + lea(dst, Address(dst, len, Address::times_1)); // byte[] + negptr(len); + + if (UseSSE42Intrinsics || UseAVX >= 2) { + Label L_chars_8_check, L_copy_8_chars, L_copy_8_chars_exit; + Label L_chars_16_check, L_copy_16_chars, L_copy_16_chars_exit; + + if (UseAVX >= 2) { + Label L_chars_32_check, L_copy_32_chars, L_copy_32_chars_exit; + movl(tmp5, 0xff00ff00); // create mask to test for Unicode chars in vector + movdl(tmp1Reg, tmp5); + vpbroadcastd(tmp1Reg, tmp1Reg); + jmpb(L_chars_32_check); + + bind(L_copy_32_chars); + vmovdqu(tmp3Reg, Address(src, len, Address::times_2, -64)); + vmovdqu(tmp4Reg, Address(src, len, Address::times_2, -32)); + vpor(tmp2Reg, tmp3Reg, tmp4Reg, /* vector256 */ true); + vptest(tmp2Reg, tmp1Reg); // check for Unicode chars in vector + jccb(Assembler::notZero, L_copy_32_chars_exit); + vpackuswb(tmp3Reg, tmp3Reg, tmp4Reg, /* vector256 */ true); + vpermq(tmp4Reg, tmp3Reg, 0xD8, /* vector256 */ true); + vmovdqu(Address(dst, len, Address::times_1, -32), tmp4Reg); + + bind(L_chars_32_check); + addptr(len, 32); + jccb(Assembler::lessEqual, L_copy_32_chars); + + bind(L_copy_32_chars_exit); + subptr(len, 16); + jccb(Assembler::greater, L_copy_16_chars_exit); + + } else if (UseSSE42Intrinsics) { + movl(tmp5, 0xff00ff00); // create mask to test for Unicode chars in vector + movdl(tmp1Reg, tmp5); + pshufd(tmp1Reg, tmp1Reg, 0); + jmpb(L_chars_16_check); + } + + bind(L_copy_16_chars); + if (UseAVX >= 2) { + vmovdqu(tmp2Reg, Address(src, len, Address::times_2, -32)); + vptest(tmp2Reg, tmp1Reg); + jccb(Assembler::notZero, L_copy_16_chars_exit); + vpackuswb(tmp2Reg, tmp2Reg, tmp1Reg, /* vector256 */ true); + vpermq(tmp3Reg, tmp2Reg, 0xD8, /* vector256 */ true); + } else { + if (UseAVX > 0) { + movdqu(tmp3Reg, Address(src, len, Address::times_2, -32)); + movdqu(tmp4Reg, Address(src, len, Address::times_2, -16)); + vpor(tmp2Reg, tmp3Reg, tmp4Reg, /* vector256 */ false); + } else { + movdqu(tmp3Reg, Address(src, len, Address::times_2, -32)); + por(tmp2Reg, tmp3Reg); + movdqu(tmp4Reg, Address(src, len, Address::times_2, -16)); + por(tmp2Reg, tmp4Reg); + } + ptest(tmp2Reg, tmp1Reg); // check for Unicode chars in vector + jccb(Assembler::notZero, L_copy_16_chars_exit); + packuswb(tmp3Reg, tmp4Reg); + } + movdqu(Address(dst, len, Address::times_1, -16), tmp3Reg); + + bind(L_chars_16_check); + addptr(len, 16); + jccb(Assembler::lessEqual, L_copy_16_chars); + + bind(L_copy_16_chars_exit); + subptr(len, 8); + jccb(Assembler::greater, L_copy_8_chars_exit); + + bind(L_copy_8_chars); + movdqu(tmp3Reg, Address(src, len, Address::times_2, -16)); + ptest(tmp3Reg, tmp1Reg); + jccb(Assembler::notZero, L_copy_8_chars_exit); + packuswb(tmp3Reg, tmp1Reg); + movq(Address(dst, len, Address::times_1, -8), tmp3Reg); + addptr(len, 8); + jccb(Assembler::lessEqual, L_copy_8_chars); + + bind(L_copy_8_chars_exit); + subptr(len, 8); + jccb(Assembler::zero, L_done); + } + + bind(L_copy_1_char); + load_unsigned_short(tmp5, Address(src, len, Address::times_2, 0)); + testl(tmp5, 0xff00); // check if Unicode char + jccb(Assembler::notZero, L_copy_1_char_exit); + movb(Address(dst, len, Address::times_1, 0), tmp5); + addptr(len, 1); + jccb(Assembler::less, L_copy_1_char); + + bind(L_copy_1_char_exit); + addptr(result, len); // len is negative count of not processed elements + bind(L_done); +} + #undef BIND #undef BLOCK_COMMENT diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index 3afcf23ebae..9500f3164fa 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -26,6 +26,7 @@ #define CPU_X86_VM_MACROASSEMBLER_X86_HPP #include "asm/assembler.hpp" +#include "utilities/macros.hpp" // MacroAssembler extends Assembler by frequently used macros. @@ -294,7 +295,7 @@ class MacroAssembler: public Assembler { void store_check(Register obj); // store check for obj - register is destroyed afterwards void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void g1_write_barrier_pre(Register obj, Register pre_val, @@ -309,7 +310,7 @@ class MacroAssembler: public Assembler { Register tmp, Register tmp2); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // split store_check(Register obj) to enhance instruction interleaving void store_check_part_1(Register obj); @@ -1135,6 +1136,10 @@ public: Register to, Register value, Register count, Register rtmp, XMMRegister xtmp); + void encode_iso_array(Register src, Register dst, Register len, + XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3, + XMMRegister tmp4, Register tmp5, Register result); + #undef VIRTUAL }; diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index aabc3dbbacd..a562bee3e53 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -44,6 +44,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #define __ _masm-> @@ -761,7 +762,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -844,7 +845,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index 3e3cc0fc1f5..26eadba79b2 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -44,6 +44,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #define __ _masm-> @@ -742,7 +743,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -821,7 +822,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index e2a20531f82..371517c0537 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #define __ _masm-> @@ -125,7 +126,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, bool precise) { assert(val == noreg || val == rax, "parameter is just for looks"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -164,7 +165,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index eedab0b4b22..d1e22d25990 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP @@ -136,7 +137,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, bool precise) { assert(val == noreg || val == rax, "parameter is just for looks"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -167,7 +168,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 8dddc9c3e1d..847d08ed207 100644 --- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp @@ -29,7 +29,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* JavaCallWrapper */ \ @@ -37,31 +37,14 @@ /******************************/ \ /* JavaFrameAnchor */ \ /******************************/ \ - volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ - \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ - /* be present there) */ + volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ - /* be present there) */ +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ - -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 75db2903b3e..90066c1041a 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -661,6 +661,14 @@ void VM_Version::get_processor_features() { } } } +#if defined(COMPILER2) && defined(_ALLBSD_SOURCE) + if (MaxVectorSize > 16) { + // Limit vectors size to 16 bytes on BSD until it fixes + // restoring upper 128bit of YMM registers on return + // from signal handler. + FLAG_SET_DEFAULT(MaxVectorSize, 16); + } +#endif // COMPILER2 // Use population count instruction if available. if (supports_popcnt()) { @@ -745,6 +753,10 @@ void VM_Version::get_processor_features() { PrefetchFieldsAhead = prefetch_fields_ahead(); #endif + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && + (cache_line_size > ContendedPaddingWidth)) + ContendedPaddingWidth = cache_line_size; + #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("Logical CPUs per core: %u", @@ -791,6 +803,9 @@ void VM_Version::get_processor_features() { if (PrefetchFieldsAhead > 0) { tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead); } + if (ContendedPaddingWidth > 0) { + tty->print_cr("ContendedPaddingWidth %d", ContendedPaddingWidth); + } } #endif // !PRODUCT } diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 462060de119..6ceb50cee84 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -11687,6 +11687,23 @@ instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI result, ins_pipe( pipe_slow ); %} +// encode char[] to byte[] in ISO_8859_1 +instruct encode_iso_array(eSIRegP src, eDIRegP dst, eDXRegI len, + regD tmp1, regD tmp2, regD tmp3, regD tmp4, + eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{ + match(Set result (EncodeISOArray src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr); + + format %{ "Encode array $src,$dst,$len -> $result // KILL ECX, EDX, $tmp1, $tmp2, $tmp3, $tmp4, ESI, EDI " %} + ins_encode %{ + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister, + $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register); + %} + ins_pipe( pipe_slow ); +%} + + //----------Control Flow Instructions------------------------------------------ // Signed compare Instructions instruct compI_eReg(eFlagsReg cr, rRegI op1, rRegI op2) %{ diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index b526a6ce27b..7c902c4e31c 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -10495,6 +10495,23 @@ instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, ins_pipe( pipe_slow ); %} +// encode char[] to byte[] in ISO_8859_1 +instruct encode_iso_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len, + regD tmp1, regD tmp2, regD tmp3, regD tmp4, + rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{ + match(Set result (EncodeISOArray src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr); + + format %{ "Encode array $src,$dst,$len -> $result // KILL RCX, RDX, $tmp1, $tmp2, $tmp3, $tmp4, RSI, RDI " %} + ins_encode %{ + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister, + $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register); + %} + ins_pipe( pipe_slow ); +%} + + //----------Control Flow Instructions------------------------------------------ // Signed compare Instructions diff --git a/hotspot/src/cpu/zero/vm/assembler_zero.cpp b/hotspot/src/cpu/zero/vm/assembler_zero.cpp index d70a2adc746..ad1107ed12f 100644 --- a/hotspot/src/cpu/zero/vm/assembler_zero.cpp +++ b/hotspot/src/cpu/zero/vm/assembler_zero.cpp @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS int AbstractAssembler::code_fill_byte() { return 0; diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index c6f82cd74a8..a199d037cbc 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -47,6 +47,7 @@ #include "runtime/vframeArray.hpp" #include "stack_zero.inline.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -791,7 +792,7 @@ address InterpreterGenerator::generate_accessor_entry() { } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -803,7 +804,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/zero/vm/frame_zero.cpp b/hotspot/src/cpu/zero/vm/frame_zero.cpp index 8643af5953f..56f2a7a1c71 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.cpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp @@ -98,10 +98,20 @@ BasicObjectLock* frame::interpreter_frame_monitor_end() const { #endif // CC_INTERP void frame::patch_pc(Thread* thread, address pc) { - // We borrow this call to set the thread pointer in the interpreter - // state; the hook to set up deoptimized frames isn't supplied it. - assert(pc == NULL, "should be"); - get_interpreterState()->set_thread((JavaThread *) thread); + + if (pc != NULL) { + _cb = CodeCache::find_blob(pc); + SharkFrame* sharkframe = zeroframe()->as_shark_frame(); + sharkframe->set_pc(pc); + _pc = pc; + _deopt_state = is_deoptimized; + + } else { + // We borrow this call to set the thread pointer in the interpreter + // state; the hook to set up deoptimized frames isn't supplied it. + assert(pc == NULL, "should be"); + get_interpreterState()->set_thread((JavaThread *) thread); + } } bool frame::safe_for_sender(JavaThread *thread) { diff --git a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp index 2bc703ae032..f6bd6d3c6be 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp @@ -45,27 +45,36 @@ inline frame::frame(ZeroFrame* zf, intptr_t* sp) { case ZeroFrame::ENTRY_FRAME: _pc = StubRoutines::call_stub_return_pc(); _cb = NULL; + _deopt_state = not_deoptimized; break; case ZeroFrame::INTERPRETER_FRAME: _pc = NULL; _cb = NULL; + _deopt_state = not_deoptimized; break; - case ZeroFrame::SHARK_FRAME: + case ZeroFrame::SHARK_FRAME: { _pc = zero_sharkframe()->pc(); _cb = CodeCache::find_blob_unsafe(pc()); + address original_pc = nmethod::get_deopt_original_pc(this); + if (original_pc != NULL) { + _pc = original_pc; + _deopt_state = is_deoptimized; + } else { + _deopt_state = not_deoptimized; + } break; - + } case ZeroFrame::FAKE_STUB_FRAME: _pc = NULL; _cb = NULL; + _deopt_state = not_deoptimized; break; default: ShouldNotReachHere(); } - _deopt_state = not_deoptimized; } // Accessors diff --git a/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp b/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp index 6c67d0eb1d8..505241b147f 100644 --- a/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp +++ b/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp @@ -68,6 +68,10 @@ class SharkFrame : public ZeroFrame { return (address) value_of_word(pc_off); } + void set_pc(address pc) const { + *((address*) addr_of_word(pc_off)) = pc; + } + intptr_t* unextended_sp() const { return (intptr_t *) value_of_word(unextended_sp_off); } diff --git a/hotspot/src/cpu/zero/vm/vmStructs_zero.hpp b/hotspot/src/cpu/zero/vm/vmStructs_zero.hpp index 1b3815a0a2c..0bbc1f40f45 100644 --- a/hotspot/src/cpu/zero/vm/vmStructs_zero.hpp +++ b/hotspot/src/cpu/zero/vm/vmStructs_zero.hpp @@ -30,28 +30,12 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ - /* be present there) */ - -#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ - -#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ - /* be present there) */ +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // CPU_ZERO_VM_VMSTRUCTS_ZERO_HPP diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index db6f3e6a0ea..477b4923e02 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -243,29 +243,32 @@ void os::Bsd::initialize_system_info() { int mib[2]; size_t len; int cpu_val; - u_long mem_val; + julong mem_val; /* get processors count via hw.ncpus sysctl */ mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(cpu_val); if (sysctl(mib, 2, &cpu_val, &len, NULL, 0) != -1 && cpu_val >= 1) { + assert(len == sizeof(cpu_val), "unexpected data size"); set_processor_count(cpu_val); } else { set_processor_count(1); // fallback } - /* get physical memory via hw.usermem sysctl (hw.usermem is used - * instead of hw.physmem because we need size of allocatable memory + /* get physical memory via hw.memsize sysctl (hw.memsize is used + * since it returns a 64 bit value) */ mib[0] = CTL_HW; - mib[1] = HW_USERMEM; + mib[1] = HW_MEMSIZE; len = sizeof(mem_val); - if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) + if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) { + assert(len == sizeof(mem_val), "unexpected data size"); _physical_memory = mem_val; - else + } else { _physical_memory = 256*1024*1024; // fallback (XXXBSD?) + } #ifdef __OpenBSD__ { @@ -4091,11 +4094,12 @@ void os::PlatformEvent::park() { // AKA "down()" } -- _nParked ; - // In theory we could move the ST of 0 into _Event past the unlock(), - // but then we'd need a MEMBAR after the ST. _Event = 0 ; status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); } guarantee (_Event >= 0, "invariant") ; } @@ -4158,40 +4162,44 @@ int os::PlatformEvent::park(jlong millis) { status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); assert (_nParked == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); return ret; } void os::PlatformEvent::unpark() { - int v, AnyWaiters ; - for (;;) { - v = _Event ; - if (v > 0) { - // The LD of _Event could have reordered or be satisfied - // by a read-aside from this processor's write buffer. - // To avoid problems execute a barrier and then - // ratify the value. - OrderAccess::fence() ; - if (_Event == v) return ; - continue ; - } - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; + // Transitions for _Event: + // 0 :=> 1 + // 1 :=> 1 + // -1 :=> either 0 or 1; must signal target thread + // That is, we can safely transition _Event from -1 to either + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back + // unpark() calls. + // See also: "Semaphores in Plan 9" by Mullender & Cox + // + // Note: Forcing a transition from "-1" to "1" on an unpark() means + // that it will take two back-to-back park() calls for the owning + // thread to block. This has the benefit of forcing a spurious return + // from the first park() call after an unpark() call which will help + // shake out uses of park() and unpark() without condition variables. + + if (Atomic::xchg(1, &_Event) >= 0) return; + + // Wait for the thread associated with the event to vacate + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + int AnyWaiters = _nParked; + assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); + if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { + AnyWaiters = 0; + pthread_cond_signal(_cond); } - if (v < 0) { - // Wait for the thread associated with the event to vacate - int status = pthread_mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - AnyWaiters = _nParked ; - assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; - if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { - AnyWaiters = 0 ; - pthread_cond_signal (_cond); - } - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - if (AnyWaiters != 0) { - status = pthread_cond_signal(_cond); - assert_status(status == 0, status, "cond_signal"); - } + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + if (AnyWaiters != 0) { + status = pthread_cond_signal(_cond); + assert_status(status == 0, status, "cond_signal"); } // Note that we signal() _after dropping the lock for "immortal" Events. @@ -4277,13 +4285,14 @@ static void unpackTime(struct timespec* absTime, bool isAbsolute, jlong time) { } void Parker::park(bool isAbsolute, jlong time) { + // Ideally we'd do something useful while spinning, such + // as calling unpackTime(). + // Optional fast-path check: // Return immediately if a permit is available. - if (_counter > 0) { - _counter = 0 ; - OrderAccess::fence(); - return ; - } + // We depend on Atomic::xchg() having full barrier semantics + // since we are doing a lock-free update to _counter. + if (Atomic::xchg(0, &_counter) > 0) return; Thread* thread = Thread::current(); assert(thread->is_Java_thread(), "Must be JavaThread"); @@ -4324,6 +4333,8 @@ void Parker::park(bool isAbsolute, jlong time) { _counter = 0; status = pthread_mutex_unlock(_mutex); assert (status == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. OrderAccess::fence(); return; } @@ -4360,12 +4371,14 @@ void Parker::park(bool isAbsolute, jlong time) { _counter = 0 ; status = pthread_mutex_unlock(_mutex) ; assert_status(status == 0, status, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. + OrderAccess::fence(); + // If externally suspended while waiting, re-suspend if (jt->handle_special_suspend_equivalent_condition()) { jt->java_suspend_self(); } - - OrderAccess::fence(); } void Parker::unpark() { diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp index 6a7cdc08b5f..8fc3c2b0878 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -59,14 +59,6 @@ inline const char* os::path_separator() { return ":"; } -inline const char* os::jlong_format_specifier() { - return "%lld"; -} - -inline const char* os::julong_format_specifier() { - return "%llu"; -} - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 8377294d20a..537b48cdbc9 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1155,13 +1155,9 @@ void os::Linux::capture_initial_stack(size_t max_size) { // for initial thread if its stack size exceeds 6M. Cap it at 2M, // in case other parts in glibc still assumes 2M max stack size. // FIXME: alt signal stack is gone, maybe we can relax this constraint? -#ifndef IA64 - if (stack_size > 2 * K * K) stack_size = 2 * K * K; -#else // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small - if (stack_size > 4 * K * K) stack_size = 4 * K * K; -#endif - + if (stack_size > 2 * K * K IA64_ONLY(*2)) + stack_size = 2 * K * K IA64_ONLY(*2); // Try to figure out where the stack base (top) is. This is harder. // // When an application is started, glibc saves the initial stack pointer in @@ -4367,16 +4363,12 @@ int os::Linux::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mute if (is_NPTL()) { return pthread_cond_timedwait(_cond, _mutex, _abstime); } else { -#ifndef IA64 // 6292965: LinuxThreads pthread_cond_timedwait() resets FPU control // word back to default 64bit precision if condvar is signaled. Java // wants 53bit precision. Save and restore current value. int fpu = get_fpu_control_word(); -#endif // IA64 int status = pthread_cond_timedwait(_cond, _mutex, _abstime); -#ifndef IA64 set_fpu_control_word(fpu); -#endif // IA64 return status; } } @@ -5001,11 +4993,12 @@ void os::PlatformEvent::park() { // AKA "down()" } -- _nParked ; - // In theory we could move the ST of 0 into _Event past the unlock(), - // but then we'd need a MEMBAR after the ST. _Event = 0 ; status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); } guarantee (_Event >= 0, "invariant") ; } @@ -5068,40 +5061,44 @@ int os::PlatformEvent::park(jlong millis) { status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); assert (_nParked == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); return ret; } void os::PlatformEvent::unpark() { - int v, AnyWaiters ; - for (;;) { - v = _Event ; - if (v > 0) { - // The LD of _Event could have reordered or be satisfied - // by a read-aside from this processor's write buffer. - // To avoid problems execute a barrier and then - // ratify the value. - OrderAccess::fence() ; - if (_Event == v) return ; - continue ; - } - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; + // Transitions for _Event: + // 0 :=> 1 + // 1 :=> 1 + // -1 :=> either 0 or 1; must signal target thread + // That is, we can safely transition _Event from -1 to either + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back + // unpark() calls. + // See also: "Semaphores in Plan 9" by Mullender & Cox + // + // Note: Forcing a transition from "-1" to "1" on an unpark() means + // that it will take two back-to-back park() calls for the owning + // thread to block. This has the benefit of forcing a spurious return + // from the first park() call after an unpark() call which will help + // shake out uses of park() and unpark() without condition variables. + + if (Atomic::xchg(1, &_Event) >= 0) return; + + // Wait for the thread associated with the event to vacate + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + int AnyWaiters = _nParked; + assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); + if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { + AnyWaiters = 0; + pthread_cond_signal(_cond); } - if (v < 0) { - // Wait for the thread associated with the event to vacate - int status = pthread_mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - AnyWaiters = _nParked ; - assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; - if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { - AnyWaiters = 0 ; - pthread_cond_signal (_cond); - } - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - if (AnyWaiters != 0) { - status = pthread_cond_signal(_cond); - assert_status(status == 0, status, "cond_signal"); - } + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + if (AnyWaiters != 0) { + status = pthread_cond_signal(_cond); + assert_status(status == 0, status, "cond_signal"); } // Note that we signal() _after dropping the lock for "immortal" Events. @@ -5187,13 +5184,14 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { } void Parker::park(bool isAbsolute, jlong time) { + // Ideally we'd do something useful while spinning, such + // as calling unpackTime(). + // Optional fast-path check: // Return immediately if a permit is available. - if (_counter > 0) { - _counter = 0 ; - OrderAccess::fence(); - return ; - } + // We depend on Atomic::xchg() having full barrier semantics + // since we are doing a lock-free update to _counter. + if (Atomic::xchg(0, &_counter) > 0) return; Thread* thread = Thread::current(); assert(thread->is_Java_thread(), "Must be JavaThread"); @@ -5234,6 +5232,8 @@ void Parker::park(bool isAbsolute, jlong time) { _counter = 0; status = pthread_mutex_unlock(_mutex); assert (status == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. OrderAccess::fence(); return; } @@ -5270,12 +5270,14 @@ void Parker::park(bool isAbsolute, jlong time) { _counter = 0 ; status = pthread_mutex_unlock(_mutex) ; assert_status(status == 0, status, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. + OrderAccess::fence(); + // If externally suspended while waiting, re-suspend if (jt->handle_special_suspend_equivalent_condition()) { jt->java_suspend_self(); } - - OrderAccess::fence(); } void Parker::unpark() { diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp index c779f8a6aa5..3a8d8d97d9b 100644 --- a/hotspot/src/os/linux/vm/os_linux.inline.hpp +++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -68,14 +68,6 @@ inline const char* os::path_separator() { return ":"; } -inline const char* os::jlong_format_specifier() { - return "%lld"; -} - -inline const char* os::julong_format_specifier() { - return "%llu"; -} - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff --git a/hotspot/src/os/posix/launcher/java_md.c b/hotspot/src/os/posix/launcher/java_md.c index 970222c4fd3..b5fc949813c 100644 --- a/hotspot/src/os/posix/launcher/java_md.c +++ b/hotspot/src/os/posix/launcher/java_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1876,11 +1876,6 @@ void SplashFreeLibrary() { } } -const char * -jlong_format_specifier() { - return "%lld"; -} - /* * Block current thread and continue execution in a new thread */ diff --git a/hotspot/src/os/posix/launcher/java_md.h b/hotspot/src/os/posix/launcher/java_md.h index ed36fd1af67..63c449a2926 100644 --- a/hotspot/src/os/posix/launcher/java_md.h +++ b/hotspot/src/os/posix/launcher/java_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -64,6 +64,12 @@ #define Counter2Micros(counts) (1) #endif /* HAVE_GETHRTIME */ +#ifdef _LP64 +#define JLONG_FORMAT "%ld" +#else +#define JLONG_FORMAT "%lld" +#endif + /* * Function prototypes. */ diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 41143af2d1a..389ed9aa294 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -6014,6 +6014,9 @@ void os::PlatformEvent::park() { // AKA: down() _Event = 0 ; status = os::Solaris::mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); } } @@ -6055,51 +6058,43 @@ int os::PlatformEvent::park(jlong millis) { _Event = 0 ; status = os::Solaris::mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); return ret; } void os::PlatformEvent::unpark() { - int v, AnyWaiters; + // Transitions for _Event: + // 0 :=> 1 + // 1 :=> 1 + // -1 :=> either 0 or 1; must signal target thread + // That is, we can safely transition _Event from -1 to either + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back + // unpark() calls. + // See also: "Semaphores in Plan 9" by Mullender & Cox + // + // Note: Forcing a transition from "-1" to "1" on an unpark() means + // that it will take two back-to-back park() calls for the owning + // thread to block. This has the benefit of forcing a spurious return + // from the first park() call after an unpark() call which will help + // shake out uses of park() and unpark() without condition variables. - // Increment _Event. - // Another acceptable implementation would be to simply swap 1 - // into _Event: - // if (Swap (&_Event, 1) < 0) { - // mutex_lock (_mutex) ; AnyWaiters = nParked; mutex_unlock (_mutex) ; - // if (AnyWaiters) cond_signal (_cond) ; - // } - - for (;;) { - v = _Event ; - if (v > 0) { - // The LD of _Event could have reordered or be satisfied - // by a read-aside from this processor's write buffer. - // To avoid problems execute a barrier and then - // ratify the value. A degenerate CAS() would also work. - // Viz., CAS (v+0, &_Event, v) == v). - OrderAccess::fence() ; - if (_Event == v) return ; - continue ; - } - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; - } + if (Atomic::xchg(1, &_Event) >= 0) return; // If the thread associated with the event was parked, wake it. - if (v < 0) { - int status ; - // Wait for the thread assoc with the PlatformEvent to vacate. - status = os::Solaris::mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - AnyWaiters = _nParked ; - status = os::Solaris::mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - guarantee (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; - if (AnyWaiters != 0) { - // We intentional signal *after* dropping the lock - // to avoid a common class of futile wakeups. - status = os::Solaris::cond_signal(_cond); - assert_status(status == 0, status, "cond_signal"); - } + // Wait for the thread assoc with the PlatformEvent to vacate. + int status = os::Solaris::mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + int AnyWaiters = _nParked; + status = os::Solaris::mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); + if (AnyWaiters != 0) { + // We intentional signal *after* dropping the lock + // to avoid a common class of futile wakeups. + status = os::Solaris::cond_signal(_cond); + assert_status(status == 0, status, "cond_signal"); } } @@ -6177,14 +6172,14 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { } void Parker::park(bool isAbsolute, jlong time) { + // Ideally we'd do something useful while spinning, such + // as calling unpackTime(). // Optional fast-path check: // Return immediately if a permit is available. - if (_counter > 0) { - _counter = 0 ; - OrderAccess::fence(); - return ; - } + // We depend on Atomic::xchg() having full barrier semantics + // since we are doing a lock-free update to _counter. + if (Atomic::xchg(0, &_counter) > 0) return; // Optional fast-exit: Check interrupt before trying to wait Thread* thread = Thread::current(); @@ -6226,6 +6221,8 @@ void Parker::park(bool isAbsolute, jlong time) { _counter = 0; status = os::Solaris::mutex_unlock(_mutex); assert (status == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. OrderAccess::fence(); return; } @@ -6267,12 +6264,14 @@ void Parker::park(bool isAbsolute, jlong time) { _counter = 0 ; status = os::Solaris::mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. + OrderAccess::fence(); // If externally suspended while waiting, re-suspend if (jt->handle_special_suspend_equivalent_condition()) { jt->java_suspend_self(); } - OrderAccess::fence(); } void Parker::unpark() { diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp index a3f09d01d32..61691fd384a 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,6 @@ inline const char* os::file_separator() { return "/"; } inline const char* os::line_separator() { return "\n"; } inline const char* os::path_separator() { return ":"; } -inline const char* os::jlong_format_specifier() { return "%lld"; } -inline const char* os::julong_format_specifier() { return "%llu"; } - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff --git a/hotspot/src/os/windows/launcher/java_md.c b/hotspot/src/os/windows/launcher/java_md.c index 2fde40ad205..3e28755009c 100644 --- a/hotspot/src/os/windows/launcher/java_md.c +++ b/hotspot/src/os/windows/launcher/java_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1323,11 +1323,6 @@ void SplashFreeLibrary() { } } -const char * -jlong_format_specifier() { - return "%I64d"; -} - /* * Block current thread and continue execution in a new thread */ diff --git a/hotspot/src/os/windows/launcher/java_md.h b/hotspot/src/os/windows/launcher/java_md.h index 111be1ee13a..763e2457644 100644 --- a/hotspot/src/os/windows/launcher/java_md.h +++ b/hotspot/src/os/windows/launcher/java_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -69,6 +69,8 @@ extern jlong Counter2Micros(jlong counts); extern int _main(int argc, char **argv); #endif +#define JLONG_FORMAT "%I64d" + /* * Function prototypes. */ diff --git a/hotspot/src/os/windows/vm/decoder_windows.cpp b/hotspot/src/os/windows/vm/decoder_windows.cpp index 82ba909bc5c..2b4682728a2 100644 --- a/hotspot/src/os/windows/vm/decoder_windows.cpp +++ b/hotspot/src/os/windows/vm/decoder_windows.cpp @@ -49,7 +49,7 @@ void WindowsDecoder::initialize() { pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions"); pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize"); _pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64"); - _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)GetProcAddress(handle, "UnDecorateSymbolName"); + _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName"); if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) { _pfnSymGetSymFromAddr64 = NULL; @@ -60,8 +60,9 @@ void WindowsDecoder::initialize() { return; } - _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); - if (!_pfnSymInitialize(GetCurrentProcess(), NULL, TRUE)) { + HANDLE hProcess = ::GetCurrentProcess(); + _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS); + if (!_pfnSymInitialize(hProcess, NULL, TRUE)) { _pfnSymGetSymFromAddr64 = NULL; _pfnUndecorateSymbolName = NULL; ::FreeLibrary(handle); @@ -70,6 +71,77 @@ void WindowsDecoder::initialize() { return; } + // set pdb search paths + pfn_SymSetSearchPath _pfn_SymSetSearchPath = + (pfn_SymSetSearchPath)::GetProcAddress(handle, "SymSetSearchPath"); + pfn_SymGetSearchPath _pfn_SymGetSearchPath = + (pfn_SymGetSearchPath)::GetProcAddress(handle, "SymGetSearchPath"); + if (_pfn_SymSetSearchPath != NULL && _pfn_SymGetSearchPath != NULL) { + char paths[MAX_PATH]; + int len = sizeof(paths); + if (!_pfn_SymGetSearchPath(hProcess, paths, len)) { + paths[0] = '\0'; + } else { + // available spaces in path buffer + len -= (int)strlen(paths); + } + + char tmp_path[MAX_PATH]; + DWORD dwSize; + HMODULE hJVM = ::GetModuleHandle("jvm.dll"); + tmp_path[0] = '\0'; + // append the path where jvm.dll is located + if (hJVM != NULL && (dwSize = ::GetModuleFileName(hJVM, tmp_path, sizeof(tmp_path))) > 0) { + while (dwSize > 0 && tmp_path[dwSize] != '\\') { + dwSize --; + } + + tmp_path[dwSize] = '\0'; + + if (dwSize > 0 && len > (int)dwSize + 1) { + strncat(paths, os::path_separator(), 1); + strncat(paths, tmp_path, dwSize); + len -= dwSize + 1; + } + } + + // append $JRE/bin. Arguments::get_java_home actually returns $JRE + // path + char *p = Arguments::get_java_home(); + assert(p != NULL, "empty java home"); + size_t java_home_len = strlen(p); + if (len > (int)java_home_len + 5) { + strncat(paths, os::path_separator(), 1); + strncat(paths, p, java_home_len); + strncat(paths, "\\bin", 4); + len -= (int)(java_home_len + 5); + } + + // append $JDK/bin path if it exists + assert(java_home_len < MAX_PATH, "Invalid path length"); + // assume $JRE is under $JDK, construct $JDK/bin path and + // see if it exists or not + if (strncmp(&p[java_home_len - 3], "jre", 3) == 0) { + strncpy(tmp_path, p, java_home_len - 3); + tmp_path[java_home_len - 3] = '\0'; + strncat(tmp_path, "bin", 3); + + // if the directory exists + DWORD dwAttrib = GetFileAttributes(tmp_path); + if (dwAttrib != INVALID_FILE_ATTRIBUTES && + (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { + // tmp_path should have the same length as java_home_len, since we only + // replaced 'jre' with 'bin' + if (len > (int)java_home_len + 1) { + strncat(paths, os::path_separator(), 1); + strncat(paths, tmp_path, java_home_len); + } + } + } + + _pfn_SymSetSearchPath(hProcess, paths); + } + // find out if jvm.dll contains private symbols, by decoding // current function and comparing the result address addr = (address)Decoder::demangle; diff --git a/hotspot/src/os/windows/vm/decoder_windows.hpp b/hotspot/src/os/windows/vm/decoder_windows.hpp index b2c2638d8ab..3008ee79136 100644 --- a/hotspot/src/os/windows/vm/decoder_windows.hpp +++ b/hotspot/src/os/windows/vm/decoder_windows.hpp @@ -35,6 +35,8 @@ typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD); typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL); typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); +typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR); +typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int); class WindowsDecoder : public AbstractDecoder { diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index b8498d5a1e2..eb16478ab8b 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -349,6 +349,33 @@ address os::current_stack_base() { #ifdef _M_IA64 // IA64 has memory and register stacks + // + // This is the stack layout you get on NT/IA64 if you specify 1MB stack limit + // at thread creation (1MB backing store growing upwards, 1MB memory stack + // growing downwards, 2MB summed up) + // + // ... + // ------- top of stack (high address) ----- + // | + // | 1MB + // | Backing Store (Register Stack) + // | + // | / \ + // | | + // | | + // | | + // ------------------------ stack base ----- + // | 1MB + // | Memory Stack + // | + // | | + // | | + // | | + // | \ / + // | + // ----- bottom of stack (low address) ----- + // ... + stack_size = stack_size / 2; #endif return stack_bottom + stack_size; @@ -1874,8 +1901,22 @@ static BOOL WINAPI consoleHandler(DWORD event) { } return TRUE; break; + case CTRL_LOGOFF_EVENT: { + // Don't terminate JVM if it is running in a non-interactive session, + // such as a service process. + USEROBJECTFLAGS flags; + HANDLE handle = GetProcessWindowStation(); + if (handle != NULL && + GetUserObjectInformation(handle, UOI_FLAGS, &flags, + sizeof( USEROBJECTFLAGS), NULL)) { + // If it is a non-interactive session, let next handler to deal + // with it. + if ((flags.dwFlags & WSF_VISIBLE) == 0) { + return FALSE; + } + } + } case CTRL_CLOSE_EVENT: - case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: os::signal_raise(SIGTERM); return TRUE; @@ -1991,17 +2032,34 @@ LONG Handle_Exception(struct _EXCEPTION_POINTERS* exceptionInfo, address handler JavaThread* thread = JavaThread::current(); // Save pc in thread #ifdef _M_IA64 - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->StIIP); + // Do not blow up if no thread info available. + if (thread) { + // Saving PRECISE pc (with slot information) in thread. + uint64_t precise_pc = (uint64_t) exceptionInfo->ExceptionRecord->ExceptionAddress; + // Convert precise PC into "Unix" format + precise_pc = (precise_pc & 0xFFFFFFFFFFFFFFF0) | ((precise_pc & 0xF) >> 2); + thread->set_saved_exception_pc((address)precise_pc); + } // Set pc to handler exceptionInfo->ContextRecord->StIIP = (DWORD64)handler; + // Clear out psr.ri (= Restart Instruction) in order to continue + // at the beginning of the target bundle. + exceptionInfo->ContextRecord->StIPSR &= 0xFFFFF9FFFFFFFFFF; + assert(((DWORD64)handler & 0xF) == 0, "Target address must point to the beginning of a bundle!"); #elif _M_AMD64 - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Rip); + // Do not blow up if no thread info available. + if (thread) { + thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Rip); + } // Set pc to handler exceptionInfo->ContextRecord->Rip = (DWORD64)handler; #else - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Eip); + // Do not blow up if no thread info available. + if (thread) { + thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Eip); + } // Set pc to handler - exceptionInfo->ContextRecord->Eip = (LONG)handler; + exceptionInfo->ContextRecord->Eip = (DWORD)(DWORD_PTR)handler; #endif // Continue the execution @@ -2026,6 +2084,14 @@ extern "C" void events(); // included or copied here. #define EXCEPTION_INFO_EXEC_VIOLATION 0x08 +// Handle NAT Bit consumption on IA64. +#ifdef _M_IA64 +#define EXCEPTION_REG_NAT_CONSUMPTION STATUS_REG_NAT_CONSUMPTION +#endif + +// Windows Vista/2008 heap corruption check +#define EXCEPTION_HEAP_CORRUPTION 0xC0000374 + #define def_excpt(val) #val, val struct siglabel { @@ -2068,6 +2134,10 @@ struct siglabel exceptlabels[] = { def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_INVALID_HANDLE), def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION), + def_excpt(EXCEPTION_HEAP_CORRUPTION), +#ifdef _M_IA64 + def_excpt(EXCEPTION_REG_NAT_CONSUMPTION), +#endif NULL, 0 }; @@ -2192,7 +2262,14 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH; DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode; #ifdef _M_IA64 - address pc = (address) exceptionInfo->ContextRecord->StIIP; + // On Itanium, we need the "precise pc", which has the slot number coded + // into the least 4 bits: 0000=slot0, 0100=slot1, 1000=slot2 (Windows format). + address pc = (address) exceptionInfo->ExceptionRecord->ExceptionAddress; + // Convert the pc to "Unix format", which has the slot number coded + // into the least 2 bits: 0000=slot0, 0001=slot1, 0010=slot2 + // This is needed for IA64 because "relocation" / "implicit null check" / "poll instruction" + // information is saved in the Unix format. + address pc_unix_format = (address) ((((uint64_t)pc) & 0xFFFFFFFFFFFFFFF0) | ((((uint64_t)pc) & 0xF) >> 2)); #elif _M_AMD64 address pc = (address) exceptionInfo->ContextRecord->Rip; #else @@ -2307,29 +2384,40 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (exception_code == EXCEPTION_STACK_OVERFLOW) { if (os::uses_stack_guard_pages()) { #ifdef _M_IA64 - // - // If it's a legal stack address continue, Windows will map it in. - // + // Use guard page for register stack. PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; address addr = (address) exceptionRecord->ExceptionInformation[1]; - if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) - return EXCEPTION_CONTINUE_EXECUTION; + // Check for a register stack overflow on Itanium + if (thread->addr_inside_register_stack_red_zone(addr)) { + // Fatal red zone violation happens if the Java program + // catches a StackOverflow error and does so much processing + // that it runs beyond the unprotected yellow guard zone. As + // a result, we are out of here. + fatal("ERROR: Unrecoverable stack overflow happened. JVM will exit."); + } else if(thread->addr_inside_register_stack(addr)) { + // Disable the yellow zone which sets the state that + // we've got a stack overflow problem. + if (thread->stack_yellow_zone_enabled()) { + thread->disable_stack_yellow_zone(); + } + // Give us some room to process the exception. + thread->disable_register_stack_guard(); + // Tracing with +Verbose. + if (Verbose) { + tty->print_cr("SOF Compiled Register Stack overflow at " INTPTR_FORMAT " (SIGSEGV)", pc); + tty->print_cr("Register Stack access at " INTPTR_FORMAT, addr); + tty->print_cr("Register Stack base " INTPTR_FORMAT, thread->register_stack_base()); + tty->print_cr("Register Stack [" INTPTR_FORMAT "," INTPTR_FORMAT "]", + thread->register_stack_base(), + thread->register_stack_base() + thread->stack_size()); + } - // The register save area is the same size as the memory stack - // and starts at the page just above the start of the memory stack. - // If we get a fault in this area, we've run out of register - // stack. If we are in java, try throwing a stack overflow exception. - if (addr > thread->stack_base() && - addr <= (thread->stack_base()+thread->stack_size()) ) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), - "Register stack overflow, addr:%p, stack_base:%p\n", - addr, thread->stack_base() ); - tty->print_raw_cr(buf); - // If not in java code, return and hope for the best. - return in_java ? Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)) - : EXCEPTION_CONTINUE_EXECUTION; + // Reguard the permanent register stack red zone just to be sure. + // We saw Windows silently disabling this without telling us. + thread->enable_register_stack_red_zone(); + + return Handle_Exception(exceptionInfo, + SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)); } #endif if (thread->stack_yellow_zone_enabled()) { @@ -2404,50 +2492,33 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { { // Null pointer exception. #ifdef _M_IA64 - // We catch register stack overflows in compiled code by doing - // an explicit compare and executing a st8(G0, G0) if the - // BSP enters into our guard area. We test for the overflow - // condition and fall into the normal null pointer exception - // code if BSP hasn't overflowed. - if ( in_java ) { - if(thread->register_stack_overflow()) { - assert((address)exceptionInfo->ContextRecord->IntS3 == - thread->register_stack_limit(), - "GR7 doesn't contain register_stack_limit"); - // Disable the yellow zone which sets the state that - // we've got a stack overflow problem. - if (thread->stack_yellow_zone_enabled()) { - thread->disable_stack_yellow_zone(); + // Process implicit null checks in compiled code. Note: Implicit null checks + // can happen even if "ImplicitNullChecks" is disabled, e.g. in vtable stubs. + if (CodeCache::contains((void*) pc_unix_format) && !MacroAssembler::needs_explicit_null_check((intptr_t) addr)) { + CodeBlob *cb = CodeCache::find_blob_unsafe(pc_unix_format); + // Handle implicit null check in UEP method entry + if (cb && (cb->is_frame_complete_at(pc) || + (cb->is_nmethod() && ((nmethod *)cb)->inlinecache_check_contains(pc)))) { + if (Verbose) { + intptr_t *bundle_start = (intptr_t*) ((intptr_t) pc_unix_format & 0xFFFFFFFFFFFFFFF0); + tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc_unix_format); + tty->print_cr(" to addr " INTPTR_FORMAT, addr); + tty->print_cr(" bundle is " INTPTR_FORMAT " (high), " INTPTR_FORMAT " (low)", + *(bundle_start + 1), *bundle_start); } - // Give us some room to process the exception - thread->disable_register_stack_guard(); - // Update GR7 with the new limit so we can continue running - // compiled code. - exceptionInfo->ContextRecord->IntS3 = - (ULONGLONG)thread->register_stack_limit(); return Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)); - } else { - // - // Check for implicit null - // We only expect null pointers in the stubs (vtable) - // the rest are checked explicitly now. - // - if (((uintptr_t)addr) < os::vm_page_size() ) { - // an access to the first page of VM--assume it is a null pointer - address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); - if (stub != NULL) return Handle_Exception(exceptionInfo, stub); - } + SharedRuntime::continuation_for_implicit_exception(thread, pc_unix_format, SharedRuntime::IMPLICIT_NULL)); } - } // in_java + } - // IA64 doesn't use implicit null checking yet. So we shouldn't - // get here. - tty->print_raw_cr("Access violation, possible null pointer exception"); + // Implicit null checks were processed above. Hence, we should not reach + // here in the usual case => die! + if (Verbose) tty->print_raw_cr("Access violation, possible null pointer exception"); report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; -#else /* !IA64 */ + +#else // !IA64 // Windows 98 reports faulting addresses incorrectly if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) || @@ -2479,7 +2550,24 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; - } + } // /EXCEPTION_ACCESS_VIOLATION + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#if defined _M_IA64 + else if ((exception_code == EXCEPTION_ILLEGAL_INSTRUCTION || + exception_code == EXCEPTION_ILLEGAL_INSTRUCTION_2)) { + M37 handle_wrong_method_break(0, NativeJump::HANDLE_WRONG_METHOD, PR0); + + // Compiled method patched to be non entrant? Following conditions must apply: + // 1. must be first instruction in bundle + // 2. must be a break instruction with appropriate code + if((((uint64_t) pc & 0x0F) == 0) && + (((IPF_Bundle*) pc)->get_slot0() == handle_wrong_method_break.bits())) { + return Handle_Exception(exceptionInfo, + (address)SharedRuntime::get_handle_wrong_method_stub()); + } + } // /EXCEPTION_ILLEGAL_INSTRUCTION +#endif + if (in_java) { switch (exception_code) { @@ -2946,7 +3034,7 @@ char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { } if( Verbose && PrintMiscellaneous ) { reserveTimer.stop(); - tty->print_cr("reserve_memory of %Ix bytes took %ld ms (%ld ticks)", bytes, + tty->print_cr("reserve_memory of %Ix bytes took " JLONG_FORMAT " ms (" JLONG_FORMAT " ticks)", bytes, reserveTimer.milliseconds(), reserveTimer.ticks()); } } @@ -4305,7 +4393,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, if (hFile == NULL) { if (PrintMiscellaneous && Verbose) { DWORD err = GetLastError(); - tty->print_cr("CreateFile() failed: GetLastError->%ld."); + tty->print_cr("CreateFile() failed: GetLastError->%ld.", err); } return NULL; } @@ -4355,7 +4443,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, if (hMap == NULL) { if (PrintMiscellaneous && Verbose) { DWORD err = GetLastError(); - tty->print_cr("CreateFileMapping() failed: GetLastError->%ld."); + tty->print_cr("CreateFileMapping() failed: GetLastError->%ld.", err); } CloseHandle(hFile); return NULL; @@ -4565,6 +4653,7 @@ int os::PlatformEvent::park (jlong Millis) { } v = _Event ; _Event = 0 ; + // see comment at end of os::PlatformEvent::park() below: OrderAccess::fence() ; // If we encounter a nearly simultanous timeout expiry and unpark() // we return OS_OK indicating we awoke via unpark(). @@ -4602,25 +4691,25 @@ void os::PlatformEvent::park () { void os::PlatformEvent::unpark() { guarantee (_ParkHandle != NULL, "Invariant") ; - int v ; - for (;;) { - v = _Event ; // Increment _Event if it's < 1. - if (v > 0) { - // If it's already signaled just return. - // The LD of _Event could have reordered or be satisfied - // by a read-aside from this processor's write buffer. - // To avoid problems execute a barrier and then - // ratify the value. A degenerate CAS() would also work. - // Viz., CAS (v+0, &_Event, v) == v). - OrderAccess::fence() ; - if (_Event == v) return ; - continue ; - } - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; - } - if (v < 0) { - ::SetEvent (_ParkHandle) ; - } + + // Transitions for _Event: + // 0 :=> 1 + // 1 :=> 1 + // -1 :=> either 0 or 1; must signal target thread + // That is, we can safely transition _Event from -1 to either + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back + // unpark() calls. + // See also: "Semaphores in Plan 9" by Mullender & Cox + // + // Note: Forcing a transition from "-1" to "1" on an unpark() means + // that it will take two back-to-back park() calls for the owning + // thread to block. This has the benefit of forcing a spurious return + // from the first park() call after an unpark() call which will help + // shake out uses of park() and unpark() without condition variables. + + if (Atomic::xchg(1, &_Event) >= 0) return; + + ::SetEvent(_ParkHandle); } diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp index 8f8c3c72fd2..1df8694d9dd 100644 --- a/hotspot/src/os/windows/vm/os_windows.inline.hpp +++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,9 +38,6 @@ inline const char* os::line_separator() { return "\r\n"; } inline const char* os::path_separator() { return ";"; } inline const char* os::dll_file_extension() { return ".dll"; } -inline const char* os::jlong_format_specifier() { return "%I64d"; } -inline const char* os::julong_format_specifier() { return "%I64u"; } - inline const int os::default_file_open_flags() { return O_BINARY | O_NOINHERIT;} // File names are case-insensitive on windows only diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index fc55e4ec71e..9eabc200bb8 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -372,7 +372,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff --git a/hotspot/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp b/hotspot/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp index b98d975408a..edfbcfa9a54 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp @@ -29,37 +29,26 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - nonstatic_field(OSThread, _pthread_id, pthread_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _pthread_id, pthread_t) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* Posix Thread IDs */ \ /**********************/ \ \ declare_unsigned_integer_type(OSThread::thread_id_t) \ - declare_unsigned_integer_type(pthread_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(pthread_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_BSD_X86_VM_VMSTRUCTS_BSD_X86_HPP diff --git a/hotspot/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp b/hotspot/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp index 17165cc9d13..6673f448f81 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp @@ -30,21 +30,13 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_BSD_ZERO_VM_VMSTRUCTS_BSD_ZERO_HPP diff --git a/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp b/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp index 58fc94bbc38..38bc63e6496 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp @@ -29,7 +29,7 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ @@ -37,38 +37,27 @@ \ nonstatic_field(JavaThread, _base_of_stack_pointer, intptr_t*) \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - nonstatic_field(OSThread, _pthread_id, pthread_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _pthread_id, pthread_t) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* POSIX Thread IDs */ \ /**********************/ \ \ declare_integer_type(OSThread::thread_id_t) \ - declare_unsigned_integer_type(pthread_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(pthread_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ \ /************************/ \ /* JavaThread constants */ \ /************************/ \ \ - declare_constant(JavaFrameAnchor::flushed) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_constant(JavaFrameAnchor::flushed) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_LINUX_SPARC_VM_VMSTRUCTS_LINUX_SPARC_HPP diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index 907395bb22a..bfb0e960a0c 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -189,7 +189,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff --git a/hotspot/src/os_cpu/linux_x86/vm/vmStructs_linux_x86.hpp b/hotspot/src/os_cpu/linux_x86/vm/vmStructs_linux_x86.hpp index c01e6c91c2a..828f992d8ba 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/vmStructs_linux_x86.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/vmStructs_linux_x86.hpp @@ -29,37 +29,26 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - nonstatic_field(OSThread, _pthread_id, pthread_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _pthread_id, pthread_t) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* Posix Thread IDs */ \ /**********************/ \ \ declare_integer_type(OSThread::thread_id_t) \ - declare_unsigned_integer_type(pthread_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(pthread_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_LINUX_X86_VM_VMSTRUCTS_LINUX_X86_HPP diff --git a/hotspot/src/os_cpu/linux_zero/vm/vmStructs_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/vmStructs_linux_zero.hpp index 46c7912c372..34b82a96d79 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/vmStructs_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/vmStructs_linux_zero.hpp @@ -30,21 +30,12 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() - -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_LINUX_ZERO_VM_VMSTRUCTS_LINUX_ZERO_HPP diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp b/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp index 58113a9ea49..40d6ae735aa 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vmStructs_solaris_sparc.hpp @@ -29,44 +29,32 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ \ nonstatic_field(JavaThread, _base_of_stack_pointer, intptr_t*) \ - nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) - -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* Solaris Thread IDs */ \ /**********************/ \ \ - declare_unsigned_integer_type(OSThread::thread_id_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(OSThread::thread_id_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ \ /************************/ \ /* JavaThread constants */ \ /************************/ \ \ - declare_constant(JavaFrameAnchor::flushed) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_constant(JavaFrameAnchor::flushed) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_SOLARIS_SPARC_VM_VMSTRUCTS_SOLARIS_SPARC_HPP diff --git a/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp b/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp index a2a4f7c60b7..523fdc7cc42 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/vmStructs_solaris_x86.hpp @@ -29,36 +29,24 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ \ - nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ /* Solaris Thread IDs */ \ /**********************/ \ \ - declare_unsigned_integer_type(OSThread::thread_id_t) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(OSThread::thread_id_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_SOLARIS_X86_VM_VMSTRUCTS_SOLARIS_X86_HPP diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index e8bd38dc13e..1ef29f99a55 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -399,7 +399,7 @@ frame os::current_frame() { typedef intptr_t* get_fp_func (); get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, StubRoutines::x86::get_previous_fp_entry()); - if (func == NULL) return frame(NULL, NULL, NULL); + if (func == NULL) return frame(); intptr_t* fp = (*func)(); #else intptr_t* fp = _get_previous_fp(); @@ -410,7 +410,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff --git a/hotspot/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp b/hotspot/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp index 69d25c93186..a392b63632c 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/vmStructs_windows_x86.hpp @@ -29,32 +29,21 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ \ /******************************/ \ /* Threads (NOTE: incomplete) */ \ /******************************/ \ \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - unchecked_nonstatic_field(OSThread, _thread_handle, sizeof(HANDLE)) /* NOTE: no type */ \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() + unchecked_nonstatic_field(OSThread, _thread_handle, sizeof(HANDLE)) /* NOTE: no type */ -#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ - declare_unsigned_integer_type(OSThread::thread_id_t) \ - /* This must be the last entry, and must be present */ \ - last_entry() + declare_unsigned_integer_type(OSThread::thread_id_t) -#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) -#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ - \ - /* This must be the last entry, and must be present */ \ - last_entry() +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #endif // OS_CPU_WINDOWS_X86_VM_VMSTRUCTS_WINDOWS_X86_HPP diff --git a/hotspot/src/share/tools/launcher/java.c b/hotspot/src/share/tools/launcher/java.c index 5ebfb9a8dc3..63f11d77c86 100644 --- a/hotspot/src/share/tools/launcher/java.c +++ b/hotspot/src/share/tools/launcher/java.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -808,7 +808,7 @@ CheckJvmType(int *pargc, char ***argv, jboolean speculative) { static int parse_stack_size(const char *s, jlong *result) { jlong n = 0; - int args_read = sscanf(s, jlong_format_specifier(), &n); + int args_read = sscanf(s, JLONG_FORMAT, &n); if (args_read != 1) { return 0; } diff --git a/hotspot/src/share/tools/launcher/java.h b/hotspot/src/share/tools/launcher/java.h index 97fba2184f7..1dd79618c84 100644 --- a/hotspot/src/share/tools/launcher/java.h +++ b/hotspot/src/share/tools/launcher/java.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -86,7 +86,6 @@ void ReportExceptionDescription(JNIEnv * env); jboolean RemovableMachineDependentOption(char * option); void PrintMachineDependentOptions(); -const char *jlong_format_specifier(); /* * Block current thread and continue execution in new thread */ diff --git a/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java b/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java index 3a8592dec58..ecc5085896f 100644 --- a/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java +++ b/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java @@ -76,4 +76,9 @@ public class WhiteBox { public native long g1NumFreeRegions(); public native int g1RegionSize(); public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); + + // NMT + public native boolean NMTAllocTest(); + public native boolean NMTFreeTestMemory(); + public native boolean NMTWaitForDataMerge(); } diff --git a/hotspot/src/share/vm/adlc/adlparse.cpp b/hotspot/src/share/vm/adlc/adlparse.cpp index 6d08eab8010..04fb735c38c 100644 --- a/hotspot/src/share/vm/adlc/adlparse.cpp +++ b/hotspot/src/share/vm/adlc/adlparse.cpp @@ -168,7 +168,7 @@ void ADLParser::instr_parse(void) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing '%{' in instruction definition\n"); + parse_err(SYNERR, "missing '%%{' in instruction definition\n"); return; } next_char(); // Maintain the invariant @@ -253,7 +253,7 @@ void ADLParser::instr_parse(void) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in instruction definition\n"); + parse_err(SYNERR, "missing '%%}' in instruction definition\n"); return; } // Check for "Set" form of chain rule @@ -423,7 +423,7 @@ void ADLParser::oper_parse(void) { skipws(); // Check for block delimiter if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block - parse_err(SYNERR, "missing '%c{' in operand definition\n","%"); + parse_err(SYNERR, "missing '%%{' in operand definition\n"); return; } next_char(); next_char(); // Skip over "%{" symbol @@ -483,7 +483,7 @@ void ADLParser::oper_parse(void) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in operand definition\n"); + parse_err(SYNERR, "missing '%%}' in operand definition\n"); return; } // Add operand to tail of operand list @@ -1324,7 +1324,7 @@ void ADLParser::pipe_parse(void) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing '%{' in pipeline definition\n"); + parse_err(SYNERR, "missing '%%{' in pipeline definition\n"); return; } next_char(); // Maintain the invariant @@ -1341,7 +1341,7 @@ void ADLParser::pipe_parse(void) { skipws(); if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "expected '%{'\n"); + parse_err(SYNERR, "expected '%%{'\n"); return; } next_char(); skipws(); @@ -1397,7 +1397,7 @@ void ADLParser::pipe_parse(void) { skipws(); if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "expected '%{'\n"); + parse_err(SYNERR, "expected '%%{'\n"); return; } next_char(); skipws(); @@ -1586,7 +1586,7 @@ void ADLParser::pipe_parse(void) { if ( (_curchar != '%') || ( next_char(), (_curchar != '}')) ) { - parse_err(SYNERR, "expected '%}', found \"%c\"\n", _curchar); + parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar); } next_char(); skipws(); @@ -1612,7 +1612,7 @@ void ADLParser::pipe_parse(void) { next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing \"%}\" in pipeline definition\n"); + parse_err(SYNERR, "missing \"%%}\" in pipeline definition\n"); return; } @@ -1775,7 +1775,7 @@ void ADLParser::pipe_class_parse(PipelineForm &pipeline) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing \"%{\" in pipe_class definition\n"); + parse_err(SYNERR, "missing \"%%{\" in pipe_class definition\n"); return; } next_char(); @@ -2062,7 +2062,7 @@ void ADLParser::pipe_class_parse(PipelineForm &pipeline) { next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing \"%}\" in pipe_class definition\n"); + parse_err(SYNERR, "missing \"%%}\" in pipe_class definition\n"); return; } @@ -3341,12 +3341,12 @@ Interface *ADLParser::mem_interface_parse(void) { char *disp = NULL; if (_curchar != '%') { - parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n"); return NULL; } next_char(); // Skip '%' if (_curchar != '{') { - parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n"); return NULL; } next_char(); // Skip '{' @@ -3354,7 +3354,7 @@ Interface *ADLParser::mem_interface_parse(void) { do { char *field = get_ident(); if (field == NULL) { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } if ( strcmp(field,"base") == 0 ) { @@ -3370,13 +3370,13 @@ Interface *ADLParser::mem_interface_parse(void) { disp = interface_field_parse(); } else { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } } while( _curchar != '%' ); next_char(); // Skip '%' if ( _curchar != '}' ) { - parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n"); return NULL; } next_char(); // Skip '}' @@ -3403,12 +3403,12 @@ Interface *ADLParser::cond_interface_parse(void) { const char *greater_format = "gt"; if (_curchar != '%') { - parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); return NULL; } next_char(); // Skip '%' if (_curchar != '{') { - parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); return NULL; } next_char(); // Skip '{' @@ -3416,7 +3416,7 @@ Interface *ADLParser::cond_interface_parse(void) { do { char *field = get_ident(); if (field == NULL) { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } if ( strcmp(field,"equal") == 0 ) { @@ -3438,13 +3438,13 @@ Interface *ADLParser::cond_interface_parse(void) { greater = interface_field_parse(&greater_format); } else { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } } while( _curchar != '%' ); next_char(); // Skip '%' if ( _curchar != '}' ) { - parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n"); return NULL; } next_char(); // Skip '}' @@ -3543,7 +3543,7 @@ MatchRule *ADLParser::match_parse(FormDict &operands) { } else if ((cnstr = find_cpp_block("match constructor")) == NULL ) { parse_err(SYNERR, "invalid construction of match rule\n" - "Missing ';' or invalid '%{' and '%}' constructor\n"); + "Missing ';' or invalid '%%{' and '%%}' constructor\n"); return NULL; // No MatchRule to return } if (_AD._adl_debug > 1) @@ -3646,7 +3646,7 @@ FormatRule* ADLParser::format_parse(void) { // Check for closing '"' and '%}' in format description skipws(); // Move to closing '%}' if ( _curchar != '%' ) { - parse_err(SYNERR, "non-blank characters between closing '\"' and '%' in format"); + parse_err(SYNERR, "non-blank characters between closing '\"' and '%%' in format"); return NULL; } } // Done with format description inside @@ -3654,7 +3654,7 @@ FormatRule* ADLParser::format_parse(void) { skipws(); // Past format description, at '%' if ( _curchar != '%' || *(_ptr+1) != '}' ) { - parse_err(SYNERR, "missing '%}' at end of format block"); + parse_err(SYNERR, "missing '%%}' at end of format block"); return NULL; } next_char(); // Move past the '%' @@ -3785,7 +3785,7 @@ FormatRule* ADLParser::template_parse(void) { skipws(); // Past format description, at '%' if ( _curchar != '%' || *(_ptr+1) != '}' ) { - parse_err(SYNERR, "missing '%}' at end of format block"); + parse_err(SYNERR, "missing '%%}' at end of format block"); return NULL; } next_char(); // Move past the '%' @@ -3834,7 +3834,7 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { skipws(); // Skip leading whitespace if ((_curchar != '%') || (next_char(), (_curchar != '{')) ) { // If not open block - parse_err(SYNERR, "missing '%{' in expand definition\n"); + parse_err(SYNERR, "missing '%%{' in expand definition\n"); return(NULL); } next_char(); // Maintain the invariant @@ -3933,7 +3933,7 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in expand rule definition\n"); + parse_err(SYNERR, "missing '%%}' in expand rule definition\n"); return(NULL); } next_char(); diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index f7f48b4a2dc..b9170ec379e 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -862,8 +862,10 @@ uint InstructForm::oper_input_base(FormDict &globals) { ( strcmp(_matrule->_rChild->_opType,"AryEq" )==0 || strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || - strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 )) { + strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 || + strcmp(_matrule->_rChild->_opType,"EncodeISOArray")==0)) { // String.(compareTo/equals/indexOf) and Arrays.equals + // and sun.nio.cs.iso8859_1$Encoder.EncodeISOArray // take 1 control and 1 memory edges. return 2; } diff --git a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp index 5b46ce1b6d0..9fbeb29b5a4 100644 --- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp +++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp @@ -31,6 +31,7 @@ #include "c1/c1_LIR.hpp" #include "c1/c1_Runtime1.hpp" #include "utilities/array.hpp" +#include "utilities/macros.hpp" class CodeEmitInfo; class LIR_Assembler; @@ -515,7 +516,7 @@ class ArrayCopyStub: public CodeStub { }; ////////////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code stubs for Garbage-First barriers. class G1PreBarrierStub: public CodeStub { @@ -608,7 +609,7 @@ class G1PostBarrierStub: public CodeStub { #endif // PRODUCT }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ////////////////////////////////////////////////////////////////////////////////////////// #endif // SHARE_VM_C1_C1_CODESTUBS_HPP diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 85c3aa1c9a9..9491607adfa 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3223,7 +3223,12 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co } if (try_inline_full(callee, holder_known, bc, receiver)) return true; - print_inlining(callee, _inline_bailout_msg, /*success*/ false); + + // Entire compilation could fail during try_inline_full call. + // In that case printing inlining decision info is useless. + if (!bailed_out()) + print_inlining(callee, _inline_bailout_msg, /*success*/ false); + return false; } @@ -3662,11 +3667,12 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode } // now perform tests that are based on flag settings - if (callee->force_inline() || callee->should_inline()) { - // ignore heuristic controls on inlining - if (callee->force_inline()) - print_inlining(callee, "force inline by annotation"); + if (callee->force_inline()) { + print_inlining(callee, "force inline by annotation"); + } else if (callee->should_inline()) { + print_inlining(callee, "force inline by CompileOracle"); } else { + // use heuristic controls on inlining if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("inlining too deep"); if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep"); if (callee->code_size_for_inlining() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); @@ -3753,7 +3759,8 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode push_scope(callee, cont); // the BlockListBuilder for the callee could have bailed out - CHECK_BAILOUT_(false); + if (bailed_out()) + return false; // Temporarily set up bytecode stream so we can append instructions // (only using the bci of this stream) @@ -3819,7 +3826,8 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode iterate_all_blocks(callee_start_block == NULL); // If we bailed out during parsing, return immediately (this is bad news) - if (bailed_out()) return false; + if (bailed_out()) + return false; // iterate_all_blocks theoretically traverses in random order; in // practice, we have only traversed the continuation if we are @@ -3828,9 +3836,6 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode !continuation()->is_set(BlockBegin::was_visited_flag), "continuation should not have been parsed yet if we created it"); - // If we bailed out during parsing, return immediately (this is bad news) - CHECK_BAILOUT_(false); - // At this point we are almost ready to return and resume parsing of // the caller back in the GraphBuilder. The only thing we want to do // first is an optimization: during parsing of the callee we @@ -4171,7 +4176,10 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes else log->inline_success("receiver is statically known"); } else { - log->inline_fail(msg); + if (msg != NULL) + log->inline_fail(msg); + else + log->inline_fail("reason unknown"); } } diff --git a/hotspot/src/share/vm/c1/c1_Instruction.cpp b/hotspot/src/share/vm/c1/c1_Instruction.cpp index 628091ce315..985cb098e6f 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.cpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp @@ -188,7 +188,7 @@ ciType* LoadIndexed::exact_type() const { ciType* LoadIndexed::declared_type() const { ciType* array_type = array()->declared_type(); - if (array_type == NULL) { + if (array_type == NULL || !array_type->is_loaded()) { return NULL; } assert(array_type->is_array_klass(), "what else?"); diff --git a/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp b/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp index a2f6f86fd85..68e0feb5b83 100644 --- a/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp +++ b/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -360,7 +360,7 @@ void InstructionPrinter::do_Constant(Constant* x) { ValueType* t = x->type(); switch (t->tag()) { case intTag : output()->print("%d" , t->as_IntConstant ()->value()); break; - case longTag : output()->print(os::jlong_format_specifier(), t->as_LongConstant()->value()); output()->print("L"); break; + case longTag : output()->print(JLONG_FORMAT, t->as_LongConstant()->value()); output()->print("L"); break; case floatTag : output()->print("%g" , t->as_FloatConstant ()->value()); break; case doubleTag : output()->print("%gD" , t->as_DoubleConstant()->value()); break; case objectTag : print_object(x); break; diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index 178d1867179..7a0563c6a20 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -1563,7 +1563,7 @@ void LIR_Const::print_value_on(outputStream* out) const { switch (type()) { case T_ADDRESS:out->print("address:%d",as_jint()); break; case T_INT: out->print("int:%d", as_jint()); break; - case T_LONG: out->print("lng:%lld", as_jlong()); break; + case T_LONG: out->print("lng:" JLONG_FORMAT, as_jlong()); break; case T_FLOAT: out->print("flt:%f", as_jfloat()); break; case T_DOUBLE: out->print("dbl:%f", as_jdouble()); break; case T_OBJECT: out->print("obj:0x%x", as_jobject()); break; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 65bc34e3de6..b46acec1474 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -35,9 +35,10 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/bitMap.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef ASSERT #define __ gen()->lir(__FILE__, __LINE__)-> @@ -1417,12 +1418,12 @@ void LIRGenerator::pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, bool do_load, bool patch, CodeEmitInfo* info) { // Do the pre-write barrier, if any. switch (_bs->kind()) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: G1SATBCardTableModRef_pre_barrier(addr_opr, pre_val, do_load, patch, info); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: // No pre barriers @@ -1439,12 +1440,12 @@ void LIRGenerator::pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { switch (_bs->kind()) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: G1SATBCardTableModRef_post_barrier(addr, new_val); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: CardTableModRef_post_barrier(addr, new_val); @@ -1459,7 +1460,7 @@ void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { } //////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void LIRGenerator::G1SATBCardTableModRef_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, bool do_load, bool patch, CodeEmitInfo* info) { @@ -1575,7 +1576,7 @@ void LIRGenerator::G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_Opr __ branch_destination(slow->continuation()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS //////////////////////////////////////////////////////////////////////// void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { @@ -2181,7 +2182,7 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) { get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile()); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We might be reading the value of the referent field of a // Reference object in order to attach it back to the live // object graph. If G1 is enabled then we need to record @@ -2311,7 +2312,7 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) { __ branch_destination(Lcont->label()); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS if (x->is_volatile() && os::is_MP()) __ membar_acquire(); } diff --git a/hotspot/src/share/vm/c1/c1_globals.hpp b/hotspot/src/share/vm/c1/c1_globals.hpp index e81636c524a..16451f6d526 100644 --- a/hotspot/src/share/vm/c1/c1_globals.hpp +++ b/hotspot/src/share/vm/c1/c1_globals.hpp @@ -147,7 +147,7 @@ "Inline methods containing exception handlers " \ "(NOTE: does not work with current backend)") \ \ - develop(bool, InlineSynchronizedMethods, true, \ + product(bool, InlineSynchronizedMethods, true, \ "Inline synchronized methods") \ \ develop(bool, InlineNIOCheckIndex, true, \ diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index bb51f88c7b9..bd18105d9ba 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -52,6 +52,7 @@ #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/dtrace.hpp" +#include "utilities/macros.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif @@ -1168,7 +1169,7 @@ void ciEnv::dump_replay_data() { void ciEnv::dump_replay_data(outputStream* out) { ASSERT_IN_VM; - + ResourceMark rm; #if INCLUDE_JVMTI out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables); out->print_cr("JvmtiExport can_hotswap_or_post_breakpoint %d", _jvmti_can_hotswap_or_post_breakpoint); diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index de5e973bfbf..d74e3693ae1 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -580,6 +580,7 @@ class StaticFinalFieldPrinter : public FieldClosure { } void do_field(fieldDescriptor* fd) { if (fd->is_final() && !fd->has_initial_value()) { + ResourceMark rm; oop mirror = fd->field_holder()->java_mirror(); _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii()); switch (fd->field_type()) { @@ -643,6 +644,8 @@ class StaticFinalFieldPrinter : public FieldClosure { void ciInstanceKlass::dump_replay_data(outputStream* out) { ASSERT_IN_VM; + ResourceMark rm; + InstanceKlass* ik = get_instanceKlass(); ConstantPool* cp = ik->constants(); diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 8ad9ecb1199..0fa11470c94 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -977,7 +977,7 @@ bool ciMethod::can_be_compiled() { // ciMethod::set_not_compilable // // Tell the VM that this method cannot be compiled at all. -void ciMethod::set_not_compilable() { +void ciMethod::set_not_compilable(const char* reason) { check_is_loaded(); VM_ENTRY_MARK; ciEnv* env = CURRENT_ENV; @@ -986,7 +986,7 @@ void ciMethod::set_not_compilable() { } else { _is_c2_compilable = false; } - get_Method()->set_not_compilable(env->comp_level()); + get_Method()->set_not_compilable(env->comp_level(), true, reason); } // ------------------------------------------------------------------ @@ -1178,6 +1178,7 @@ ciMethodBlocks *ciMethod::get_method_blocks() { void ciMethod::dump_replay_data(outputStream* st) { ASSERT_IN_VM; + ResourceMark rm; Method* method = get_Method(); Klass* holder = method->method_holder(); st->print_cr("ciMethod %s %s %s %d %d %d %d %d", diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index 193eb68de05..c98f2c0dccf 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -252,7 +252,7 @@ class ciMethod : public ciMetadata { bool has_option(const char *option); bool can_be_compiled(); bool can_be_osr_compiled(int entry_bci); - void set_not_compilable(); + void set_not_compilable(const char* reason = NULL); bool has_compiled_code(); void log_nmethod_identity(xmlStream* log); bool is_not_reached(int bci); diff --git a/hotspot/src/share/vm/ci/ciMethodData.cpp b/hotspot/src/share/vm/ci/ciMethodData.cpp index ee5490be877..c30c6c36437 100644 --- a/hotspot/src/share/vm/ci/ciMethodData.cpp +++ b/hotspot/src/share/vm/ci/ciMethodData.cpp @@ -374,6 +374,7 @@ void ciMethodData::print_impl(outputStream* st) { void ciMethodData::dump_replay_data(outputStream* out) { ASSERT_IN_VM; + ResourceMark rm; MethodData* mdo = get_MethodData(); Method* method = mdo->method(); Klass* holder = method->method_holder(); diff --git a/hotspot/src/share/vm/ci/ciReplay.cpp b/hotspot/src/share/vm/ci/ciReplay.cpp index f2e77241960..030d93db7c3 100644 --- a/hotspot/src/share/vm/ci/ciReplay.cpp +++ b/hotspot/src/share/vm/ci/ciReplay.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 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 @@ -30,6 +30,7 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "utilities/copy.hpp" +#include "utilities/macros.hpp" #ifndef PRODUCT @@ -645,7 +646,7 @@ class CompileReplay : public StackObj { java_mirror->bool_field_put(fd.offset(), value); } else if (strcmp(field_signature, "J") == 0) { jlong value; - if (sscanf(string_value, INT64_FORMAT, &value) != 1) { + if (sscanf(string_value, JLONG_FORMAT, &value) != 1) { fprintf(stderr, "Error parsing long: %s\n", string_value); return; } diff --git a/hotspot/src/share/vm/ci/ciType.cpp b/hotspot/src/share/vm/ci/ciType.cpp index 47412130f04..e74dd921804 100644 --- a/hotspot/src/share/vm/ci/ciType.cpp +++ b/hotspot/src/share/vm/ci/ciType.cpp @@ -59,6 +59,19 @@ bool ciType::is_subtype_of(ciType* type) { return false; } +// ------------------------------------------------------------------ +// ciType::name +// +// Return the name of this type +const char* ciType::name() { + if (is_primitive_type()) { + return type2name(basic_type()); + } else { + assert(is_klass(), "must be"); + return as_klass()->name()->as_utf8(); + } +} + // ------------------------------------------------------------------ // ciType::print_impl // @@ -73,7 +86,8 @@ void ciType::print_impl(outputStream* st) { // // Print the name of this type void ciType::print_name_on(outputStream* st) { - st->print(type2name(basic_type())); + ResourceMark rm; + st->print(name()); } diff --git a/hotspot/src/share/vm/ci/ciType.hpp b/hotspot/src/share/vm/ci/ciType.hpp index 807ae1bec92..25f79e01263 100644 --- a/hotspot/src/share/vm/ci/ciType.hpp +++ b/hotspot/src/share/vm/ci/ciType.hpp @@ -77,6 +77,7 @@ public: bool is_type() const { return true; } bool is_classless() const { return is_primitive_type(); } + const char* name(); virtual void print_name_on(outputStream* st); void print_name() { print_name_on(tty); diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 9dd0640de06..d46a1eab840 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,7 @@ #include "services/classLoadingService.hpp" #include "services/threadService.hpp" #include "utilities/array.hpp" +#include "utilities/globalDefinitions.hpp" // We generally try to create the oops directly when parsing, rather than // allocating temporary data structures and copying the bytes twice. A @@ -970,6 +971,12 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + parse_annotations(loader_data, + runtime_visible_annotations, + runtime_visible_annotations_length, + cp, + parsed_annotations, + CHECK); cfs->skip_u1(runtime_visible_annotations_length, CHECK); } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = attribute_length; @@ -1216,19 +1223,16 @@ Array* ClassFileParser::parse_fields(ClassLoaderData* loader_data, field->initialize(access_flags.as_short(), name_index, signature_index, - constantvalue_index, - 0); - if (parsed_annotations.has_any_annotations()) - parsed_annotations.apply_to(field); - + constantvalue_index); BasicType type = cp->basic_type_for_signature_at(signature_index); // Remember how many oops we encountered and compute allocation type FieldAllocationType atype = fac->update(is_static, type); + field->set_allocation_type(atype); - // The correct offset is computed later (all oop fields will be located together) - // We temporarily store the allocation type in the offset field - field->set_offset(atype); + // After field is initialized with type, we can augment it with aux info + if (parsed_annotations.has_any_annotations()) + parsed_annotations.apply_to(field); } int index = length; @@ -1259,17 +1263,13 @@ Array* ClassFileParser::parse_fields(ClassLoaderData* loader_data, field->initialize(JVM_ACC_FIELD_INTERNAL, injected[n].name_index, injected[n].signature_index, - 0, 0); BasicType type = FieldType::basic_type(injected[n].signature()); // Remember how many oops we encountered and compute allocation type FieldAllocationType atype = fac->update(false, type); - - // The correct offset is computed later (all oop fields will be located together) - // We temporarily store the allocation type in the offset field - field->set_offset(atype); + field->set_allocation_type(atype); index++; } } @@ -1735,7 +1735,8 @@ int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) { } // Sift through annotations, looking for those significant to the VM: -void ClassFileParser::parse_annotations(u1* buffer, int limit, +void ClassFileParser::parse_annotations(ClassLoaderData* loader_data, + u1* buffer, int limit, constantPoolHandle cp, ClassFileParser::AnnotationCollector* coll, TRAPS) { @@ -1752,9 +1753,12 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit, e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;' e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME' e_size = 11, // end of 'e' annotation - c_tag_val = 'c', - c_con_off = 7, // utf8 payload, such as 'I' or 'Ljava/lang/String;' + c_tag_val = 'c', // payload is type + c_con_off = 7, // utf8 payload, such as 'I' c_size = 9, // end of 'c' annotation + s_tag_val = 's', // payload is String + s_con_off = 7, // utf8 payload, such as 'Ljava/lang/String;' + s_size = 9, min_size = 6 // smallest possible size (zero members) }; while ((--nann) >= 0 && (index-2 + min_size <= limit)) { @@ -1773,57 +1777,63 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit, } // Here is where parsing particular annotations will take place. - AnnotationCollector::ID id = coll->annotation_index(aname); + AnnotationCollector::ID id = coll->annotation_index(loader_data, aname); if (id == AnnotationCollector::_unknown) continue; coll->set_annotation(id); - // If there are no values, just set the bit and move on: - if (count == 0) continue; - // For the record, here is how annotation payloads can be collected. - // Suppose we want to capture @Retention.value. Here is how: - //if (id == AnnotationCollector::_class_Retention) { - // Symbol* payload = NULL; - // if (count == 1 - // && e_size == (index0 - index) // match size - // && e_tag_val == *(abase + tag_off) - // && (check_symbol_at(cp, Bytes::get_Java_u2(abase + e_type_off)) - // == vmSymbols::RetentionPolicy_signature()) - // && member == vmSymbols::value_name()) { - // payload = check_symbol_at(cp, Bytes::get_Java_u2(abase + e_con_off)); - // } - // check_property(payload != NULL, - // "Invalid @Retention annotation at offset %u in class file %s", - // index0, CHECK); - // if (payload != NULL) { - // payload->increment_refcount(); - // coll->_class_RetentionPolicy = payload; - // } - //} + if (id == AnnotationCollector::_sun_misc_Contended) { + if (count == 1 + && s_size == (index - index0) // match size + && s_tag_val == *(abase + tag_off) + && member == vmSymbols::value_name()) { + u2 group_index = Bytes::get_Java_u2(abase + s_con_off); + coll->set_contended_group(group_index); + } else { + coll->set_contended_group(0); // default contended group + } + coll->set_contended(true); + } else { + coll->set_contended(false); + } } } -ClassFileParser::AnnotationCollector::ID ClassFileParser::AnnotationCollector::annotation_index(Symbol* name) { +ClassFileParser::AnnotationCollector::ID +ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_data, + Symbol* name) { vmSymbols::SID sid = vmSymbols::find_sid(name); + // Privileged code can use all annotations. Other code silently drops some. + bool privileged = loader_data->is_the_null_class_loader_data() || + loader_data->is_anonymous(); switch (sid) { case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature): if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code return _method_ForceInline; case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_DontInline_signature): if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code return _method_DontInline; case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Compiled_signature): if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code return _method_LambdaForm_Compiled; case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Hidden_signature): if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code return _method_LambdaForm_Hidden; + case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Contended_signature): + if (_location != _in_field && _location != _in_class) break; // only allow for fields and classes + if (!EnableContended || (RestrictContended && !privileged)) break; // honor privileges + return _sun_misc_Contended; default: break; } return AnnotationCollector::_unknown; } void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) { - fatal("no field annotations yet"); + if (is_contended()) + f->set_contended_group(contended_group()); } void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) { @@ -1838,7 +1848,7 @@ void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) { } void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) { - fatal("no class annotations yet"); + k->set_is_contended(is_contended()); } @@ -1937,6 +1947,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, u2** localvariable_type_table_start; u2 method_parameters_length = 0; u1* method_parameters_data = NULL; + bool method_parameters_seen = false; + bool method_parameters_four_byte_flags; bool parsed_code_attribute = false; bool parsed_checked_exceptions_attribute = false; bool parsed_stackmap_attribute = false; @@ -2147,10 +2159,32 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, method_attribute_length, cp, CHECK_(nullHandle)); } else if (method_attribute_name == vmSymbols::tag_method_parameters()) { + // reject multiple method parameters + if (method_parameters_seen) { + classfile_parse_error("Multiple MethodParameters attributes in class file %s", CHECK_(nullHandle)); + } + method_parameters_seen = true; method_parameters_length = cfs->get_u1_fast(); + // Track the actual size (note: this is written for clarity; a + // decent compiler will CSE and constant-fold this into a single + // expression) + // Use the attribute length to figure out the size of flags + if (method_attribute_length == (method_parameters_length * 6u) + 1u) { + method_parameters_four_byte_flags = true; + } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) { + method_parameters_four_byte_flags = false; + } else { + classfile_parse_error( + "Invalid MethodParameters method attribute length %u in class file", + method_attribute_length, CHECK_(nullHandle)); + } method_parameters_data = cfs->get_u1_buffer(); cfs->skip_u2_fast(method_parameters_length); - cfs->skip_u4_fast(method_parameters_length); + if (method_parameters_four_byte_flags) { + cfs->skip_u4_fast(method_parameters_length); + } else { + cfs->skip_u2_fast(method_parameters_length); + } // ignore this attribute if it cannot be reflected if (!SystemDictionary::Parameter_klass_loaded()) method_parameters_length = 0; @@ -2181,7 +2215,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, runtime_visible_annotations_length = method_attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); - parse_annotations(runtime_visible_annotations, + parse_annotations(loader_data, + runtime_visible_annotations, runtime_visible_annotations_length, cp, &parsed_annotations, CHECK_(nullHandle)); cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle)); @@ -2293,12 +2328,16 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, // Copy method parameters if (method_parameters_length > 0) { MethodParametersElement* elem = m->constMethod()->method_parameters_start(); - for(int i = 0; i < method_parameters_length; i++) { - elem[i].name_cp_index = - Bytes::get_Java_u2(method_parameters_data); + for (int i = 0; i < method_parameters_length; i++) { + elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data); method_parameters_data += 2; - elem[i].flags = Bytes::get_Java_u4(method_parameters_data); - method_parameters_data += 4; + if (method_parameters_four_byte_flags) { + elem[i].flags = Bytes::get_Java_u4(method_parameters_data); + method_parameters_data += 4; + } else { + elem[i].flags = Bytes::get_Java_u2(method_parameters_data); + method_parameters_data += 2; + } } } @@ -2475,26 +2514,38 @@ Array* ClassFileParser::parse_methods(ClassLoaderData* loader_data, *has_default_methods = true; } methods->at_put(index, method()); - if (*methods_annotations == NULL) { - *methods_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + + if (method_annotations != NULL) { + if (*methods_annotations == NULL) { + *methods_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_annotations)->at_put(index, method_annotations); } - (*methods_annotations)->at_put(index, method_annotations); - if (*methods_parameter_annotations == NULL) { - *methods_parameter_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + + if (method_parameter_annotations != NULL) { + if (*methods_parameter_annotations == NULL) { + *methods_parameter_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_parameter_annotations)->at_put(index, method_parameter_annotations); } - (*methods_parameter_annotations)->at_put(index, method_parameter_annotations); - if (*methods_default_annotations == NULL) { - *methods_default_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + + if (method_default_annotations != NULL) { + if (*methods_default_annotations == NULL) { + *methods_default_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_default_annotations)->at_put(index, method_default_annotations); } - (*methods_default_annotations)->at_put(index, method_default_annotations); - if (*methods_type_annotations == NULL) { - *methods_type_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + + if (method_type_annotations != NULL) { + if (*methods_type_annotations == NULL) { + *methods_type_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_type_annotations)->at_put(index, method_type_annotations); } - (*methods_type_annotations)->at_put(index, method_type_annotations); } if (_need_verify && length > 1) { @@ -2886,7 +2937,8 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); - parse_annotations(runtime_visible_annotations, + parse_annotations(loader_data, + runtime_visible_annotations, runtime_visible_annotations_length, cp, parsed_annotations, @@ -3309,8 +3361,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, bool has_final_method = false; AccessFlags promoted_flags; promoted_flags.set_flags(0); - // These need to be oop pointers because they are allocated lazily - // inside parse_methods inside a nested HandleMark + Array* methods_annotations = NULL; Array* methods_parameter_annotations = NULL; Array* methods_default_annotations = NULL; @@ -3405,18 +3456,21 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // Size of Java itable (in words) itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces); + // get the padding width from the option + // TODO: Ask VM about specific CPU we are running on + int pad_size = ContendedPaddingWidth; + // Field size and offset computation int nonstatic_field_size = super_klass() == NULL ? 0 : super_klass->nonstatic_field_size(); #ifndef PRODUCT int orig_nonstatic_field_size = 0; #endif - int static_field_size = 0; int next_static_oop_offset; int next_static_double_offset; int next_static_word_offset; int next_static_short_offset; int next_static_byte_offset; - int next_static_type_offset; + int next_static_padded_offset; int next_nonstatic_oop_offset; int next_nonstatic_double_offset; int next_nonstatic_word_offset; @@ -3426,11 +3480,36 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, int first_nonstatic_oop_offset; int first_nonstatic_field_offset; int next_nonstatic_field_offset; + int next_nonstatic_padded_offset; + + // Count the contended fields by type. + int static_contended_count = 0; + int nonstatic_contended_count = 0; + FieldAllocationCount fac_contended; + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); + if (fs.is_contended()) { + fac_contended.count[atype]++; + if (fs.access_flags().is_static()) { + static_contended_count++; + } else { + nonstatic_contended_count++; + } + } + } + int contended_count = static_contended_count + nonstatic_contended_count; + // Calculate the starting byte offsets next_static_oop_offset = InstanceMirrorKlass::offset_of_static_fields(); + + // class is contended, pad before all the fields + if (parsed_annotations.is_contended()) { + next_static_oop_offset += pad_size; + } + next_static_double_offset = next_static_oop_offset + - (fac.count[STATIC_OOP] * heapOopSize); + ((fac.count[STATIC_OOP] - fac_contended.count[STATIC_OOP]) * heapOopSize); if ( fac.count[STATIC_DOUBLE] && (Universe::field_type_should_be_aligned(T_DOUBLE) || Universe::field_type_should_be_aligned(T_LONG)) ) { @@ -3438,25 +3517,29 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, } next_static_word_offset = next_static_double_offset + - (fac.count[STATIC_DOUBLE] * BytesPerLong); + ((fac.count[STATIC_DOUBLE] - fac_contended.count[STATIC_DOUBLE]) * BytesPerLong); next_static_short_offset = next_static_word_offset + - (fac.count[STATIC_WORD] * BytesPerInt); + ((fac.count[STATIC_WORD] - fac_contended.count[STATIC_WORD]) * BytesPerInt); next_static_byte_offset = next_static_short_offset + - (fac.count[STATIC_SHORT] * BytesPerShort); - next_static_type_offset = align_size_up((next_static_byte_offset + - fac.count[STATIC_BYTE] ), wordSize ); - static_field_size = (next_static_type_offset - - next_static_oop_offset) / wordSize; + ((fac.count[STATIC_SHORT] - fac_contended.count[STATIC_SHORT]) * BytesPerShort); + next_static_padded_offset = next_static_byte_offset + + ((fac.count[STATIC_BYTE] - fac_contended.count[STATIC_BYTE]) * 1); first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size * heapOopSize; + + // class is contended, pad before all the fields + if (parsed_annotations.is_contended()) { + first_nonstatic_field_offset += pad_size; + } + next_nonstatic_field_offset = first_nonstatic_field_offset; - unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE]; - unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD]; - unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT]; - unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE]; - unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP]; + unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE]; + unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD] - fac_contended.count[NONSTATIC_WORD]; + unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT] - fac_contended.count[NONSTATIC_SHORT]; + unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE] - fac_contended.count[NONSTATIC_BYTE]; + unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP] - fac_contended.count[NONSTATIC_OOP]; bool super_has_nonstatic_fields = (super_klass() != NULL && super_klass->has_nonstatic_fields()); @@ -3529,12 +3612,12 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, } if( allocation_style == 0 ) { - // Fields order: oops, longs/doubles, ints, shorts/chars, bytes + // Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields next_nonstatic_oop_offset = next_nonstatic_field_offset; next_nonstatic_double_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); } else if( allocation_style == 1 ) { - // Fields order: longs/doubles, ints, shorts/chars, bytes, oops + // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields next_nonstatic_double_offset = next_nonstatic_field_offset; } else if( allocation_style == 2 ) { // Fields allocation: oops fields in super and sub classes are together. @@ -3613,27 +3696,33 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, (nonstatic_word_count * BytesPerInt); next_nonstatic_byte_offset = next_nonstatic_short_offset + (nonstatic_short_count * BytesPerShort); + next_nonstatic_padded_offset = next_nonstatic_byte_offset + + nonstatic_byte_count; - int notaligned_offset; - if( allocation_style == 0 ) { - notaligned_offset = next_nonstatic_byte_offset + nonstatic_byte_count; - } else { // allocation_style == 1 - next_nonstatic_oop_offset = next_nonstatic_byte_offset + nonstatic_byte_count; + // let oops jump before padding with this allocation style + if( allocation_style == 1 ) { + next_nonstatic_oop_offset = next_nonstatic_padded_offset; if( nonstatic_oop_count > 0 ) { next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize); } - notaligned_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); + next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); } - next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize ); - nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset - - first_nonstatic_field_offset)/heapOopSize); // Iterate over fields again and compute correct offsets. // The field allocation type was temporarily stored in the offset slot. // oop fields are located before non-oop fields (static and non-static). for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + + // skip already laid out fields + if (fs.is_offset_set()) continue; + + // contended fields are handled below + if (fs.is_contended()) continue; + int real_offset; - FieldAllocationType atype = (FieldAllocationType) fs.offset(); + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); + + // pack the rest of the fields switch (atype) { case STATIC_OOP: real_offset = next_static_oop_offset; @@ -3722,13 +3811,225 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, fs.set_offset(real_offset); } + + // Handle the contended cases. + // + // Each contended field should not intersect the cache line with another contended field. + // In the absence of alignment information, we end up with pessimistically separating + // the fields with full-width padding. + // + // Additionally, this should not break alignment for the fields, so we round the alignment up + // for each field. + if (contended_count > 0) { + + // if there is at least one contended field, we need to have pre-padding for them + if (nonstatic_contended_count > 0) { + next_nonstatic_padded_offset += pad_size; + } + + // collect all contended groups + BitMap bm(cp->size()); + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + // skip already laid out fields + if (fs.is_offset_set()) continue; + + if (fs.is_contended()) { + bm.set_bit(fs.contended_group()); + } + } + + int current_group = -1; + while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) { + + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + + // skip already laid out fields + if (fs.is_offset_set()) continue; + + // skip non-contended fields and fields from different group + if (!fs.is_contended() || (fs.contended_group() != current_group)) continue; + + // handle statics below + if (fs.access_flags().is_static()) continue; + + int real_offset; + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); + + switch (atype) { + case NONSTATIC_BYTE: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, 1); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += 1; + break; + + case NONSTATIC_SHORT: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerShort); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += BytesPerShort; + break; + + case NONSTATIC_WORD: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerInt); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += BytesPerInt; + break; + + case NONSTATIC_DOUBLE: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, BytesPerLong); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += BytesPerLong; + break; + + case NONSTATIC_OOP: + next_nonstatic_padded_offset = align_size_up(next_nonstatic_padded_offset, heapOopSize); + real_offset = next_nonstatic_padded_offset; + next_nonstatic_padded_offset += heapOopSize; + + // Create new oop map + nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset; + nonstatic_oop_counts [nonstatic_oop_map_count] = 1; + nonstatic_oop_map_count += 1; + if( first_nonstatic_oop_offset == 0 ) { // Undefined + first_nonstatic_oop_offset = real_offset; + } + break; + + default: + ShouldNotReachHere(); + } + + if (fs.contended_group() == 0) { + // Contended group defines the equivalence class over the fields: + // the fields within the same contended group are not inter-padded. + // The only exception is default group, which does not incur the + // equivalence, and so requires intra-padding. + next_nonstatic_padded_offset += pad_size; + } + + fs.set_offset(real_offset); + } // for + + // Start laying out the next group. + // Note that this will effectively pad the last group in the back; + // this is expected to alleviate memory contention effects for + // subclass fields and/or adjacent object. + // If this was the default group, the padding is already in place. + if (current_group != 0) { + next_nonstatic_padded_offset += pad_size; + } + } + + // handle static fields + + // if there is at least one contended field, we need to have pre-padding for them + if (static_contended_count > 0) { + next_static_padded_offset += pad_size; + } + + current_group = -1; + while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) { + + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + + // skip already laid out fields + if (fs.is_offset_set()) continue; + + // skip non-contended fields and fields from different group + if (!fs.is_contended() || (fs.contended_group() != current_group)) continue; + + // non-statics already handled above + if (!fs.access_flags().is_static()) continue; + + int real_offset; + FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); + + switch (atype) { + + case STATIC_BYTE: + next_static_padded_offset = align_size_up(next_static_padded_offset, 1); + real_offset = next_static_padded_offset; + next_static_padded_offset += 1; + break; + + case STATIC_SHORT: + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerShort); + real_offset = next_static_padded_offset; + next_static_padded_offset += BytesPerShort; + break; + + case STATIC_WORD: + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerInt); + real_offset = next_static_padded_offset; + next_static_padded_offset += BytesPerInt; + break; + + case STATIC_DOUBLE: + next_static_padded_offset = align_size_up(next_static_padded_offset, BytesPerLong); + real_offset = next_static_padded_offset; + next_static_padded_offset += BytesPerLong; + break; + + case STATIC_OOP: + next_static_padded_offset = align_size_up(next_static_padded_offset, heapOopSize); + real_offset = next_static_padded_offset; + next_static_padded_offset += heapOopSize; + break; + + default: + ShouldNotReachHere(); + } + + if (fs.contended_group() == 0) { + // Contended group defines the equivalence class over the fields: + // the fields within the same contended group are not inter-padded. + // The only exception is default group, which does not incur the + // equivalence, and so requires intra-padding. + next_static_padded_offset += pad_size; + } + + fs.set_offset(real_offset); + } // for + + // Start laying out the next group. + // Note that this will effectively pad the last group in the back; + // this is expected to alleviate memory contention effects for + // subclass fields and/or adjacent object. + // If this was the default group, the padding is already in place. + if (current_group != 0) { + next_static_padded_offset += pad_size; + } + + } + + } // handle contended + // Size of instances int instance_size; + int notaligned_offset = next_nonstatic_padded_offset; + + // Entire class is contended, pad in the back. + // This helps to alleviate memory contention effects for subclass fields + // and/or adjacent object. + if (parsed_annotations.is_contended()) { + notaligned_offset += pad_size; + next_static_padded_offset += pad_size; + } + + int next_static_type_offset = align_size_up(next_static_padded_offset, wordSize); + int static_field_size = (next_static_type_offset - + InstanceMirrorKlass::offset_of_static_fields()) / wordSize; + + next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize ); + nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset + - first_nonstatic_field_offset)/heapOopSize); + next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize ); instance_size = align_object_size(next_nonstatic_type_offset / wordSize); - assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value"); + assert(instance_size == align_object_size(align_size_up( + (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize + ((parsed_annotations.is_contended()) ? pad_size : 0)), + wordSize) / wordSize), "consistent layout helper value"); // Number of non-static oop map blocks allocated at end of klass. const unsigned int total_oop_map_count = @@ -3912,7 +4213,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // check that if this class is an interface then it doesn't have static methods if (this_klass->is_interface()) { - check_illegal_static_method(this_klass, CHECK_(nullHandle)); + /* An interface in a JAVA 8 classfile can be static */ + if (_major_version < JAVA_8_VERSION) { + check_illegal_static_method(this_klass, CHECK_(nullHandle)); + } } @@ -4005,6 +4309,18 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, } #endif +#ifndef PRODUCT + if (PrintFieldLayout) { + print_field_layout(name, + fields, + cp, + instance_size, + first_nonstatic_field_offset, + next_nonstatic_field_offset, + next_static_type_offset); + } +#endif + // preserve result across HandleMark preserve_this_klass = this_klass(); } @@ -4017,6 +4333,38 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, return this_klass; } +void ClassFileParser::print_field_layout(Symbol* name, + Array* fields, + constantPoolHandle cp, + int instance_size, + int instance_fields_start, + int instance_fields_end, + int static_fields_end) { + tty->print("%s: field layout\n", name->as_klass_external_name()); + tty->print(" @%3d %s\n", instance_fields_start, "--- instance fields start ---"); + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + if (!fs.access_flags().is_static()) { + tty->print(" @%3d \"%s\" %s\n", + fs.offset(), + fs.name()->as_klass_external_name(), + fs.signature()->as_klass_external_name()); + } + } + tty->print(" @%3d %s\n", instance_fields_end, "--- instance fields end ---"); + tty->print(" @%3d %s\n", instance_size * wordSize, "--- instance ends ---"); + tty->print(" @%3d %s\n", InstanceMirrorKlass::offset_of_static_fields(), "--- static fields start ---"); + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + tty->print(" @%3d \"%s\" %s\n", + fs.offset(), + fs.name()->as_klass_external_name(), + fs.signature()->as_klass_external_name()); + } + } + tty->print(" @%3d %s\n", static_fields_end, "--- static fields end ---"); + tty->print("\n"); +} + unsigned int ClassFileParser::compute_oop_map_count(instanceKlassHandle super, unsigned int nonstatic_oop_map_count, @@ -4466,6 +4814,7 @@ void ClassFileParser::verify_legal_method_modifiers( const bool is_bridge = (flags & JVM_ACC_BRIDGE) != 0; const bool is_strict = (flags & JVM_ACC_STRICT) != 0; const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0; + const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION; const bool major_gte_8 = _major_version >= JAVA_8_VERSION; const bool is_initializer = (name == vmSymbols::object_initializer_name()); @@ -4473,11 +4822,33 @@ void ClassFileParser::verify_legal_method_modifiers( bool is_illegal = false; if (is_interface) { - if (!is_public || is_static || is_final || is_native || - ((is_synchronized || is_strict) && major_gte_15 && - (!major_gte_8 || is_abstract)) || - (!major_gte_8 && !is_abstract)) { - is_illegal = true; + if (major_gte_8) { + // Class file version is JAVA_8_VERSION or later Methods of + // interfaces may set any of the flags except ACC_PROTECTED, + // ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED; they must + // have exactly one of the ACC_PUBLIC or ACC_PRIVATE flags set. + if ((is_public == is_private) || /* Only one of private and public should be true - XNOR */ + (is_native || is_protected || is_final || is_synchronized) || + // If a specific method of a class or interface has its + // ACC_ABSTRACT flag set, it must not have any of its + // ACC_FINAL, ACC_NATIVE, ACC_PRIVATE, ACC_STATIC, + // ACC_STRICT, or ACC_SYNCHRONIZED flags set. No need to + // check for ACC_FINAL, ACC_NATIVE or ACC_SYNCHRONIZED as + // those flags are illegal irrespective of ACC_ABSTRACT being set or not. + (is_abstract && (is_private || is_static || is_strict))) { + is_illegal = true; + } + } else if (major_gte_15) { + // Class file version in the interval [JAVA_1_5_VERSION, JAVA_8_VERSION) + if (!is_public || is_static || is_final || is_synchronized || + is_native || !is_abstract || is_strict) { + is_illegal = true; + } + } else { + // Class file version is pre-JAVA_1_5_VERSION + if (!is_public || is_static || is_final || is_native || !is_abstract) { + is_illegal = true; + } } } else { // not interface if (is_initializer) { diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index 5a5d3fc397a..cc0193a15f5 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -95,17 +95,20 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { _method_DontInline, _method_LambdaForm_Compiled, _method_LambdaForm_Hidden, + _sun_misc_Contended, _annotation_LIMIT }; const Location _location; int _annotations_present; + u2 _contended_group; + AnnotationCollector(Location location) : _location(location), _annotations_present(0) { assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, ""); } // If this annotation name has an ID, report it (or _none). - ID annotation_index(Symbol* name); + ID annotation_index(ClassLoaderData* loader_data, Symbol* name); // Set the annotation name: void set_annotation(ID id) { assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); @@ -114,6 +117,12 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { // Report if the annotation is present. bool has_any_annotations() { return _annotations_present != 0; } bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; } + + void set_contended_group(u2 group) { _contended_group = group; } + u2 contended_group() { return _contended_group; } + + void set_contended(bool contended) { set_annotation(_sun_misc_Contended); } + bool is_contended() { return has_annotation(_sun_misc_Contended); } }; class FieldAnnotationCollector: public AnnotationCollector { public: @@ -177,6 +186,14 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { Array** fields_type_annotations, u2* java_fields_count_ptr, TRAPS); + void print_field_layout(Symbol* name, + Array* fields, + constantPoolHandle cp, + int instance_size, + int instance_fields_start, + int instance_fields_end, + int static_fields_end); + // Method parsing methodHandle parse_method(ClassLoaderData* loader_data, constantPoolHandle cp, @@ -247,7 +264,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { int runtime_invisible_annotations_length, TRAPS); int skip_annotation(u1* buffer, int limit, int index); int skip_annotation_value(u1* buffer, int limit, int index); - void parse_annotations(u1* buffer, int limit, constantPoolHandle cp, + void parse_annotations(ClassLoaderData* loader_data, + u1* buffer, int limit, constantPoolHandle cp, /* Results (currently, only one result is supported): */ AnnotationCollector* result, TRAPS); diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 40c397de887..e74a88d7d33 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -50,11 +50,12 @@ #include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" -#include "prims/jvmtiRedefineClasses.hpp" +#include "memory/oopFactory.hpp" #include "runtime/jniHandles.hpp" #include "runtime/mutex.hpp" #include "runtime/safepoint.hpp" @@ -318,6 +319,7 @@ ClassLoaderData::~ClassLoaderData() { } Metaspace* ClassLoaderData::metaspace_non_null() { + assert(!DumpSharedSpaces, "wrong metaspace!"); // If the metaspace has not been allocated, create a new one. Might want // to create smaller arena for Reflection class loaders also. // The reason for the delayed allocation is because some class loaders are @@ -722,13 +724,13 @@ void ClassLoaderDataGraph::dump_on(outputStream * const out) { } MetaspaceAux::dump(out); } +#endif // PRODUCT void ClassLoaderData::print_value_on(outputStream* out) const { if (class_loader() == NULL) { - out->print_cr("NULL class_loader"); + out->print("NULL class_loader"); } else { out->print("class loader "PTR_FORMAT, this); class_loader()->print_value_on(out); } } -#endif // PRODUCT diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index 9525658e67a..f72645db1c4 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -220,7 +220,7 @@ class ClassLoaderData : public CHeapObj { void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } void print_value() { print_value_on(tty); } - void print_value_on(outputStream* out) const PRODUCT_RETURN; + void print_value_on(outputStream* out) const; void dump(outputStream * const out) PRODUCT_RETURN; void verify(); const char* loader_name(); diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp index ac593a7ef24..ce516b84bc1 100644 --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp @@ -1285,13 +1285,15 @@ static void merge_in_new_methods(InstanceKlass* klass, enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS }; - Array* original_annots[NUM_ARRAYS]; + Array* original_annots[NUM_ARRAYS] = { NULL }; Array* original_methods = klass->methods(); Annotations* annots = klass->annotations(); - original_annots[ANNOTATIONS] = annots->methods_annotations(); - original_annots[PARAMETERS] = annots->methods_parameter_annotations(); - original_annots[DEFAULTS] = annots->methods_default_annotations(); + if (annots != NULL) { + original_annots[ANNOTATIONS] = annots->methods_annotations(); + original_annots[PARAMETERS] = annots->methods_parameter_annotations(); + original_annots[DEFAULTS] = annots->methods_default_annotations(); + } Array* original_ordering = klass->method_ordering(); Array* merged_ordering = Universe::the_empty_int_array(); @@ -1370,9 +1372,15 @@ static void merge_in_new_methods(InstanceKlass* klass, // Replace klass methods with new merged lists klass->set_methods(merged_methods); - annots->set_methods_annotations(merged_annots[ANNOTATIONS]); - annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]); - annots->set_methods_default_annotations(merged_annots[DEFAULTS]); + if (annots != NULL) { + annots->set_methods_annotations(merged_annots[ANNOTATIONS]); + annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]); + annots->set_methods_default_annotations(merged_annots[DEFAULTS]); + } else { + assert(merged_annots[ANNOTATIONS] == NULL, "Must be"); + assert(merged_annots[PARAMETERS] == NULL, "Must be"); + assert(merged_annots[DEFAULTS] == NULL, "Must be"); + } ClassLoaderData* cld = klass->class_loader_data(); MetadataFactory::free_array(cld, original_methods); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index cb30a83d455..fe03d3fb132 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -687,19 +687,6 @@ void java_lang_Class::set_array_klass(oop java_class, Klass* klass) { } -Method* java_lang_Class::resolved_constructor(oop java_class) { - Metadata* constructor = java_class->metadata_field(_resolved_constructor_offset); - assert(constructor == NULL || constructor->is_method(), "should be method"); - return ((Method*)constructor); -} - - -void java_lang_Class::set_resolved_constructor(oop java_class, Method* constructor) { - assert(constructor->is_method(), "should be method"); - java_class->metadata_field_put(_resolved_constructor_offset, constructor); -} - - bool java_lang_Class::is_primitive(oop java_class) { // should assert: //assert(java_lang_Class::is_instance(java_class), "must be a Class object"); @@ -924,7 +911,6 @@ jlong java_lang_Thread::stackSize(oop java_thread) { // Write the thread status value to threadStatus field in java.lang.Thread java class. void java_lang_Thread::set_thread_status(oop java_thread, java_lang_Thread::ThreadStatus status) { - assert(JavaThread::current()->thread_state() == _thread_in_vm, "Java Thread is not running in vm"); // The threadStatus is only present starting in 1.5 if (_thread_status_offset > 0) { java_thread->int_field_put(_thread_status_offset, status); @@ -1158,179 +1144,43 @@ void java_lang_Throwable::print(Handle throwable, outputStream* st) { } } -// Print stack trace element to resource allocated buffer -char* java_lang_Throwable::print_stack_element_to_buffer(Method* method, int bci) { - // Get strings and string lengths - InstanceKlass* klass = method->method_holder(); - const char* klass_name = klass->external_name(); - int buf_len = (int)strlen(klass_name); - char* source_file_name; - if (klass->source_file_name() == NULL) { - source_file_name = NULL; - } else { - source_file_name = klass->source_file_name()->as_C_string(); - buf_len += (int)strlen(source_file_name); - } - char* method_name = method->name()->as_C_string(); - buf_len += (int)strlen(method_name); +// After this many redefines, the stack trace is unreliable. +const int MAX_VERSION = USHRT_MAX; - // Allocate temporary buffer with extra space for formatting and line number - char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); +// Helper backtrace functions to store bci|version together. +static inline int merge_bci_and_version(int bci, int version) { + // only store u2 for version, checking for overflow. + if (version > USHRT_MAX || version < 0) version = MAX_VERSION; + assert((jushort)bci == bci, "bci should be short"); + return build_int_from_shorts(version, bci); +} - // Print stack trace line in buffer - sprintf(buf, "\tat %s.%s", klass_name, method_name); +static inline int bci_at(unsigned int merged) { + return extract_high_short_from_int(merged); +} +static inline int version_at(unsigned int merged) { + return extract_low_short_from_int(merged); +} + +static inline bool version_matches(Method* method, int version) { + return (method->constants()->version() == version && version < MAX_VERSION); +} + +static inline int get_line_number(Method* method, int bci) { + int line_number = 0; if (method->is_native()) { - strcat(buf, "(Native Method)"); + // Negative value different from -1 below, enabling Java code in + // class java.lang.StackTraceElement to distinguish "native" from + // "no LineNumberTable". JDK tests for -2. + line_number = -2; } else { - int line_number = method->line_number_from_bci(bci); - if (source_file_name != NULL && (line_number != -1)) { - // Sourcename and linenumber - sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number); - } else if (source_file_name != NULL) { - // Just sourcename - sprintf(buf + (int)strlen(buf), "(%s)", source_file_name); - } else { - // Neither soucename and linenumber - sprintf(buf + (int)strlen(buf), "(Unknown Source)"); - } - nmethod* nm = method->code(); - if (WizardMode && nm != NULL) { - sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); + // Returns -1 if no LineNumberTable, and otherwise actual line number + line_number = method->line_number_from_bci(bci); + if (line_number == -1 && ShowHiddenFrames) { + line_number = bci + 1000000; } } - - return buf; -} - - -void java_lang_Throwable::print_stack_element(Handle stream, Method* method, int bci) { - ResourceMark rm; - char* buf = print_stack_element_to_buffer(method, bci); - print_to_stream(stream, buf); -} - -void java_lang_Throwable::print_stack_element(outputStream *st, Method* method, int bci) { - ResourceMark rm; - char* buf = print_stack_element_to_buffer(method, bci); - st->print_cr("%s", buf); -} - -void java_lang_Throwable::print_to_stream(Handle stream, const char* str) { - if (stream.is_null()) { - tty->print_cr("%s", str); - } else { - EXCEPTION_MARK; - JavaValue result(T_VOID); - Handle arg (THREAD, oopFactory::new_charArray(str, THREAD)); - if (!HAS_PENDING_EXCEPTION) { - JavaCalls::call_virtual(&result, - stream, - KlassHandle(THREAD, stream->klass()), - vmSymbols::println_name(), - vmSymbols::char_array_void_signature(), - arg, - THREAD); - } - // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. - if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION; - } - -} - - -const char* java_lang_Throwable::no_stack_trace_message() { - return "\t<>"; -} - - -// Currently used only for exceptions occurring during startup -void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { - Thread *THREAD = Thread::current(); - Handle h_throwable(THREAD, throwable); - while (h_throwable.not_null()) { - objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); - if (result.is_null()) { - st->print_cr(no_stack_trace_message()); - return; - } - - while (result.not_null()) { - typeArrayHandle methods (THREAD, - typeArrayOop(result->obj_at(trace_methods_offset))); - typeArrayHandle bcis (THREAD, - typeArrayOop(result->obj_at(trace_bcis_offset))); - - if (methods.is_null() || bcis.is_null()) { - st->print_cr(no_stack_trace_message()); - return; - } - - int length = methods()->length(); - for (int index = 0; index < length; index++) { - Method* method = ((Method*)methods()->metadata_at(index)); - if (method == NULL) goto handle_cause; - int bci = bcis->ushort_at(index); - print_stack_element(st, method, bci); - } - result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); - } - handle_cause: - { - EXCEPTION_MARK; - JavaValue result(T_OBJECT); - JavaCalls::call_virtual(&result, - h_throwable, - KlassHandle(THREAD, h_throwable->klass()), - vmSymbols::getCause_name(), - vmSymbols::void_throwable_signature(), - THREAD); - // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - h_throwable = Handle(); - } else { - h_throwable = Handle(THREAD, (oop) result.get_jobject()); - if (h_throwable.not_null()) { - st->print("Caused by: "); - print(h_throwable, st); - st->cr(); - } - } - } - } -} - - -void java_lang_Throwable::print_stack_trace(oop throwable, oop print_stream) { - // Note: this is no longer used in Merlin, but we support it for compatibility. - Thread *thread = Thread::current(); - Handle stream(thread, print_stream); - objArrayHandle result (thread, objArrayOop(backtrace(throwable))); - if (result.is_null()) { - print_to_stream(stream, no_stack_trace_message()); - return; - } - - while (result.not_null()) { - typeArrayHandle methods(thread, - typeArrayOop(result->obj_at(trace_methods_offset))); - typeArrayHandle bcis (thread, - typeArrayOop(result->obj_at(trace_bcis_offset))); - - if (methods.is_null() || bcis.is_null()) { - print_to_stream(stream, no_stack_trace_message()); - return; - } - - int length = methods()->length(); - for (int index = 0; index < length; index++) { - Method* method = ((Method*)methods()->metadata_at(index)); - if (method == NULL) return; - int bci = bcis->ushort_at(index); - print_stack_element(stream, method, bci); - } - result = objArrayHandle(thread, objArrayOop(result->obj_at(trace_next_offset))); - } + return line_number; } // This class provides a simple wrapper over the internal structure of @@ -1350,13 +1200,30 @@ class BacktraceBuilder: public StackObj { enum { trace_methods_offset = java_lang_Throwable::trace_methods_offset, - trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, + trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, trace_next_offset = java_lang_Throwable::trace_next_offset, trace_size = java_lang_Throwable::trace_size, trace_chunk_size = java_lang_Throwable::trace_chunk_size }; + // get info out of chunks + static typeArrayOop get_methods(objArrayHandle chunk) { + typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); + assert(methods != NULL, "method array should be initialized in backtrace"); + return methods; + } + static typeArrayOop get_bcis(objArrayHandle chunk) { + typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); + assert(bcis != NULL, "bci array should be initialized in backtrace"); + return bcis; + } + static objArrayOop get_mirrors(objArrayHandle chunk) { + objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); + assert(mirrors != NULL, "mirror array should be initialized in backtrace"); + return mirrors; + } + // constructor for new backtrace BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) { expand(CHECK); @@ -1364,6 +1231,19 @@ class BacktraceBuilder: public StackObj { _index = 0; } + BacktraceBuilder(objArrayHandle backtrace) { + _methods = get_methods(backtrace); + _bcis = get_bcis(backtrace); + _mirrors = get_mirrors(backtrace); + assert(_methods->length() == _bcis->length() && + _methods->length() == _mirrors->length(), + "method and source information arrays should match"); + + // head is the preallocated backtrace + _backtrace = _head = backtrace(); + _index = 0; + } + void expand(TRAPS) { objArrayHandle old_head(THREAD, _head); Pause_No_Safepoint_Verifier pnsv(&_nsv); @@ -1371,10 +1251,10 @@ class BacktraceBuilder: public StackObj { objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK); objArrayHandle new_head(THREAD, head); - typeArrayOop methods = oopFactory::new_metaDataArray(trace_chunk_size, CHECK); + typeArrayOop methods = oopFactory::new_shortArray(trace_chunk_size, CHECK); typeArrayHandle new_methods(THREAD, methods); - typeArrayOop bcis = oopFactory::new_shortArray(trace_chunk_size, CHECK); + typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK); typeArrayHandle new_bcis(THREAD, bcis); objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); @@ -1389,7 +1269,7 @@ class BacktraceBuilder: public StackObj { _head = new_head(); _methods = new_methods(); - _bcis = new_bcis(); + _bcis = new_bcis(); _mirrors = new_mirrors(); _index = 0; } @@ -1403,7 +1283,6 @@ class BacktraceBuilder: public StackObj { // shorts. The later line number lookup would just smear the -1 // to a 0 even if it could be recorded. if (bci == SynchronizationEntryBCI) bci = 0; - assert(bci == (jushort)bci, "doesn't fit"); if (_index >= trace_chunk_size) { methodHandle mhandle(THREAD, method); @@ -1411,26 +1290,148 @@ class BacktraceBuilder: public StackObj { method = mhandle(); } - _methods->metadata_at_put(_index, method); - _bcis->ushort_at_put(_index, bci); - // we need to save the mirrors in the backtrace to keep the methods from - // being unloaded if their class loader is unloaded while we still have - // this stack trace. + _methods->short_at_put(_index, method->method_idnum()); + _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); + + // We need to save the mirrors in the backtrace to keep the class + // from being unloaded while we still have this stack trace. + assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); _index++; } - Method* current_method() { - assert(_index >= 0 && _index < trace_chunk_size, "out of range"); - return ((Method*)_methods->metadata_at(_index)); - } - - jushort current_bci() { - assert(_index >= 0 && _index < trace_chunk_size, "out of range"); - return _bcis->ushort_at(_index); - } }; +// Print stack trace element to resource allocated buffer +char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, + int method_id, int version, int bci) { + + // Get strings and string lengths + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); + const char* klass_name = holder->external_name(); + int buf_len = (int)strlen(klass_name); + + // pushing to the stack trace added one. + Method* method = holder->method_with_idnum(method_id); + char* method_name = method->name()->as_C_string(); + buf_len += (int)strlen(method_name); + + char* source_file_name = NULL; + if (version_matches(method, version)) { + Symbol* source = holder->source_file_name(); + if (source != NULL) { + source_file_name = source->as_C_string(); + buf_len += (int)strlen(source_file_name); + } + } + + // Allocate temporary buffer with extra space for formatting and line number + char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); + + // Print stack trace line in buffer + sprintf(buf, "\tat %s.%s", klass_name, method_name); + + if (!version_matches(method, version)) { + strcat(buf, "(Redefined)"); + } else { + int line_number = get_line_number(method, bci); + if (line_number == -2) { + strcat(buf, "(Native Method)"); + } else { + if (source_file_name != NULL && (line_number != -1)) { + // Sourcename and linenumber + sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number); + } else if (source_file_name != NULL) { + // Just sourcename + sprintf(buf + (int)strlen(buf), "(%s)", source_file_name); + } else { + // Neither sourcename nor linenumber + sprintf(buf + (int)strlen(buf), "(Unknown Source)"); + } + nmethod* nm = method->code(); + if (WizardMode && nm != NULL) { + sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); + } + } + } + + return buf; +} + +void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, + int method_id, int version, int bci) { + ResourceMark rm; + char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci); + st->print_cr("%s", buf); +} + +void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) { + Handle mirror = method->method_holder()->java_mirror(); + int method_id = method->method_idnum(); + int version = method->constants()->version(); + print_stack_element(st, mirror, method_id, version, bci); +} + +const char* java_lang_Throwable::no_stack_trace_message() { + return "\t<>"; +} + + +// Currently used only for exceptions occurring during startup +void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { + Thread *THREAD = Thread::current(); + Handle h_throwable(THREAD, throwable); + while (h_throwable.not_null()) { + objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); + if (result.is_null()) { + st->print_cr(no_stack_trace_message()); + return; + } + + while (result.not_null()) { + + // Get method id, bci, version and mirror from chunk + typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); + typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); + objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); + + int length = methods()->length(); + for (int index = 0; index < length; index++) { + Handle mirror(THREAD, mirrors->obj_at(index)); + // NULL mirror means end of stack trace + if (mirror.is_null()) goto handle_cause; + int method = methods->short_at(index); + int version = version_at(bcis->int_at(index)); + int bci = bci_at(bcis->int_at(index)); + print_stack_element(st, mirror, method, version, bci); + } + result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); + } + handle_cause: + { + EXCEPTION_MARK; + JavaValue cause(T_OBJECT); + JavaCalls::call_virtual(&cause, + h_throwable, + KlassHandle(THREAD, h_throwable->klass()), + vmSymbols::getCause_name(), + vmSymbols::void_throwable_signature(), + THREAD); + // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + h_throwable = Handle(); + } else { + h_throwable = Handle(THREAD, (oop) cause.get_jobject()); + if (h_throwable.not_null()) { + st->print("Caused by: "); + print(h_throwable, st); + st->cr(); + } + } + } + } +} void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS) { if (!StackTraceInThrowable) return; @@ -1591,21 +1592,8 @@ void java_lang_Throwable::allocate_backtrace(Handle throwable, TRAPS) { // No-op if stack trace is disabled if (!StackTraceInThrowable) return; - - objArrayOop h_oop = oopFactory::new_objectArray(trace_size, CHECK); - objArrayHandle backtrace (THREAD, h_oop); - typeArrayOop m_oop = oopFactory::new_metaDataArray(trace_chunk_size, CHECK); - typeArrayHandle methods (THREAD, m_oop); - typeArrayOop b = oopFactory::new_shortArray(trace_chunk_size, CHECK); - typeArrayHandle bcis(THREAD, b); - objArrayOop mirror_oop = oopFactory::new_objectArray(trace_chunk_size, CHECK); - objArrayHandle mirrors (THREAD, mirror_oop); - - // backtrace has space for one chunk (next is NULL) - backtrace->obj_at_put(trace_methods_offset, methods()); - backtrace->obj_at_put(trace_bcis_offset, bcis()); - backtrace->obj_at_put(trace_mirrors_offset, mirrors()); - set_backtrace(throwable(), backtrace()); + BacktraceBuilder bt(CHECK); // creates a backtrace + set_backtrace(throwable(), bt.backtrace()); } @@ -1617,48 +1605,26 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check"); - objArrayOop backtrace = (objArrayOop)java_lang_Throwable::backtrace(throwable()); - assert(backtrace != NULL, "backtrace not preallocated"); + JavaThread* THREAD = JavaThread::current(); - oop m = backtrace->obj_at(trace_methods_offset); - typeArrayOop methods = typeArrayOop(m); - assert(methods != NULL && methods->length() > 0, "method array not preallocated"); + objArrayHandle backtrace (THREAD, (objArrayOop)java_lang_Throwable::backtrace(throwable())); + assert(backtrace.not_null(), "backtrace should have been preallocated"); - oop b = backtrace->obj_at(trace_bcis_offset); - typeArrayOop bcis = typeArrayOop(b); - assert(bcis != NULL, "bci array not preallocated"); + ResourceMark rm(THREAD); + vframeStream st(THREAD); - oop mr = backtrace->obj_at(trace_mirrors_offset); - objArrayOop mirrors = objArrayOop(mr); - assert(mirrors != NULL, "bci array not preallocated"); - - assert(methods->length() == bcis->length() && - methods->length() == mirrors->length(), - "method and bci arrays should match"); - - JavaThread* thread = JavaThread::current(); - ResourceMark rm(thread); - vframeStream st(thread); + BacktraceBuilder bt(backtrace); // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init // methods as preallocated errors aren't created by "java" code. // fill in as much stack trace as possible + typeArrayOop methods = BacktraceBuilder::get_methods(backtrace); int max_chunks = MIN2(methods->length(), (int)MaxJavaStackTraceDepth); int chunk_count = 0; for (;!st.at_end(); st.next()) { - // Add entry and smear the -1 bci to 0 since the array only holds - // unsigned shorts. The later line number lookup would just smear - // the -1 to a 0 even if it could be recorded. - int bci = st.bci(); - if (bci == SynchronizationEntryBCI) bci = 0; - assert(bci == (jushort)bci, "doesn't fit"); - bcis->ushort_at_put(chunk_count, bci); - methods->metadata_at_put(chunk_count, st.method()); - mirrors->obj_at_put(chunk_count, - st.method()->method_holder()->java_mirror()); - + bt.push(st.method(), st.bci(), CHECK); chunk_count++; // Bail-out for deep stacks @@ -1672,7 +1638,6 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace()); assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized"); } - } @@ -1691,12 +1656,12 @@ int java_lang_Throwable::get_stack_trace_depth(oop throwable, TRAPS) { chunk = next; } assert(chunk != NULL && chunk->obj_at(trace_next_offset) == NULL, "sanity check"); - // Count element in remaining partial chunk - typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); - typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); - assert(methods != NULL && bcis != NULL, "sanity check"); - for (int i = 0; i < methods->length(); i++) { - if (methods->metadata_at(i) == NULL) break; + // Count element in remaining partial chunk. NULL value for mirror + // marks the end of the stack trace elements that are saved. + objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); + assert(mirrors != NULL, "sanity check"); + for (int i = 0; i < mirrors->length(); i++) { + if (mirrors->obj_at(i) == NULL) break; depth++; } } @@ -1722,25 +1687,28 @@ oop java_lang_Throwable::get_stack_trace_element(oop throwable, int index, TRAPS if (chunk == NULL) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - // Get method,bci from chunk - typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); - typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); - assert(methods != NULL && bcis != NULL, "sanity check"); - methodHandle method(THREAD, ((Method*)methods->metadata_at(chunk_index))); - int bci = bcis->ushort_at(chunk_index); + // Get method id, bci, version and mirror from chunk + typeArrayOop methods = BacktraceBuilder::get_methods(chunk); + typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); + objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); + + assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); + + int method = methods->short_at(chunk_index); + int version = version_at(bcis->int_at(chunk_index)); + int bci = bci_at(bcis->int_at(chunk_index)); + Handle mirror(THREAD, mirrors->obj_at(chunk_index)); + // Chunk can be partial full - if (method.is_null()) { + if (mirror.is_null()) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - oop element = java_lang_StackTraceElement::create(method, bci, CHECK_0); + oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0); return element; } -oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { - // SystemDictionary::stackTraceElement_klass() will be null for pre-1.4 JDKs - assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4"); - +oop java_lang_StackTraceElement::create(Handle mirror, int method_id, int version, int bci, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); @@ -1752,37 +1720,39 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { Handle element = ik->allocate_instance_handle(CHECK_0); // Fill in class name ResourceMark rm(THREAD); - const char* str = method->method_holder()->external_name(); + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); + const char* str = holder->external_name(); oop classname = StringTable::intern((char*) str, CHECK_0); java_lang_StackTraceElement::set_declaringClass(element(), classname); + // Fill in method name + Method* method = holder->method_with_idnum(method_id); oop methodname = StringTable::intern(method->name(), CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); - // Fill in source file name - Symbol* source = method->method_holder()->source_file_name(); - if (ShowHiddenFrames && source == NULL) - source = vmSymbols::unknown_class_name(); - oop filename = StringTable::intern(source, CHECK_0); - java_lang_StackTraceElement::set_fileName(element(), filename); - // File in source line number - int line_number; - if (method->is_native()) { - // Negative value different from -1 below, enabling Java code in - // class java.lang.StackTraceElement to distinguish "native" from - // "no LineNumberTable". - line_number = -2; - } else { - // Returns -1 if no LineNumberTable, and otherwise actual line number - line_number = method->line_number_from_bci(bci); - if (line_number == -1 && ShowHiddenFrames) { - line_number = bci + 1000000; - } - } - java_lang_StackTraceElement::set_lineNumber(element(), line_number); + if (!version_matches(method, version)) { + // The method was redefined, accurate line number information isn't available + java_lang_StackTraceElement::set_fileName(element(), NULL); + java_lang_StackTraceElement::set_lineNumber(element(), -1); + } else { + // Fill in source file name and line number. + Symbol* source = holder->source_file_name(); + if (ShowHiddenFrames && source == NULL) + source = vmSymbols::unknown_class_name(); + oop filename = StringTable::intern(source, CHECK_0); + java_lang_StackTraceElement::set_fileName(element(), filename); + + int line_number = get_line_number(method, bci); + java_lang_StackTraceElement::set_lineNumber(element(), line_number); + } return element(); } +oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { + Handle mirror (THREAD, method->method_holder()->java_mirror()); + int method_id = method->method_idnum(); + return create(mirror, method_id, method->constants()->version(), bci, THREAD); +} void java_lang_reflect_AccessibleObject::compute_offsets() { Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); @@ -2949,7 +2919,6 @@ int java_lang_System::err_offset_in_bytes() { int java_lang_Class::_klass_offset; int java_lang_Class::_array_klass_offset; -int java_lang_Class::_resolved_constructor_offset; int java_lang_Class::_oop_size_offset; int java_lang_Class::_static_oop_field_count_offset; GrowableArray* java_lang_Class::_fixup_mirror_list = NULL; @@ -3303,7 +3272,6 @@ void JavaClasses::check_offsets() { // Fake fields // CHECK_OFFSET("java/lang/Class", java_lang_Class, klass); // %%% this needs to be checked // CHECK_OFFSET("java/lang/Class", java_lang_Class, array_klass); // %%% this needs to be checked - // CHECK_OFFSET("java/lang/Class", java_lang_Class, resolved_constructor); // %%% this needs to be checked // java.lang.Throwable diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 5ab16251c10..478509d5c66 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -206,7 +206,6 @@ class java_lang_String : AllStatic { #define CLASS_INJECTED_FIELDS(macro) \ macro(java_lang_Class, klass, intptr_signature, false) \ - macro(java_lang_Class, resolved_constructor, intptr_signature, false) \ macro(java_lang_Class, array_klass, intptr_signature, false) \ macro(java_lang_Class, oop_size, int_signature, false) \ macro(java_lang_Class, static_oop_field_count, int_signature, false) @@ -218,7 +217,6 @@ class java_lang_Class : AllStatic { // The fake offsets are added by the class loader when java.lang.Class is loaded static int _klass_offset; - static int _resolved_constructor_offset; static int _array_klass_offset; static int _oop_size_offset; @@ -254,15 +252,11 @@ class java_lang_Class : AllStatic { static bool is_primitive(oop java_class); static BasicType primitive_type(oop java_class); static oop primitive_mirror(BasicType t); - // JVM_NewInstance support - static Method* resolved_constructor(oop java_class); - static void set_resolved_constructor(oop java_class, Method* constructor); // JVM_NewArray support static Klass* array_klass(oop java_class); static void set_array_klass(oop java_class, Klass* klass); // compiler support for class operations static int klass_offset_in_bytes() { return _klass_offset; } - static int resolved_constructor_offset_in_bytes() { return _resolved_constructor_offset; } static int array_klass_offset_in_bytes() { return _array_klass_offset; } // Support for classRedefinedCount field static int classRedefinedCount(oop the_class_mirror); @@ -469,8 +463,7 @@ class java_lang_Throwable: AllStatic { static int static_unassigned_stacktrace_offset; // Printing - static char* print_stack_element_to_buffer(Method* method, int bci); - static void print_to_stream(Handle stream, const char* str); + static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci); // StackTrace (programmatic access, new since 1.4) static void clear_stacktrace(oop throwable); // No stack trace available @@ -490,12 +483,9 @@ class java_lang_Throwable: AllStatic { static oop message(oop throwable); static oop message(Handle throwable); static void set_message(oop throwable, oop value); - // Print stack trace stored in exception by call-back to Java - // Note: this is no longer used in Merlin, but we still suppport - // it for compatibility. - static void print_stack_trace(oop throwable, oop print_stream); - static void print_stack_element(Handle stream, Method* method, int bci); - static void print_stack_element(outputStream *st, Method* method, int bci); + static void print_stack_element(outputStream *st, Handle mirror, int method, + int version, int bci); + static void print_stack_element(outputStream *st, methodHandle method, int bci); static void print_stack_usage(Handle stream); // Allocate space for backtrace (created but stack trace not filled in) @@ -1263,7 +1253,8 @@ class java_lang_StackTraceElement: AllStatic { static void set_lineNumber(oop element, int value); // Create an instance of StackTraceElement - static oop create(methodHandle m, int bci, TRAPS); + static oop create(Handle mirror, int method, int version, int bci, TRAPS); + static oop create(methodHandle method, int bci, TRAPS); // Debugging friend class JavaClasses; diff --git a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp new file mode 100644 index 00000000000..1f24042f5cb --- /dev/null +++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 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. + * + */ + +#include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" +#include "code/codeCache.hpp" +#include "compiler/compileBroker.hpp" +#include "oops/metadata.hpp" +#include "runtime/synchronizer.hpp" +#include "runtime/thread.hpp" +#include "utilities/growableArray.hpp" + + +// Keep track of marked on-stack metadata so it can be cleared. +GrowableArray* _marked_objects = NULL; +NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) + +// Walk metadata on the stack and mark it so that redefinition doesn't delete +// it. Class unloading also walks the previous versions and might try to +// delete it, so this class is used by class unloading also. +MetadataOnStackMark::MetadataOnStackMark() { + assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); + NOT_PRODUCT(_is_active = true;) + if (_marked_objects == NULL) { + _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray(1000, true); + } + Threads::metadata_do(Metadata::mark_on_stack); + CodeCache::alive_nmethods_do(nmethod::mark_on_stack); + CompileBroker::mark_on_stack(); +} + +MetadataOnStackMark::~MetadataOnStackMark() { + assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); + // Unmark everything that was marked. Can't do the same walk because + // redefine classes messes up the code cache so the set of methods + // might not be the same. + for (int i = 0; i< _marked_objects->length(); i++) { + _marked_objects->at(i)->set_on_stack(false); + } + _marked_objects->clear(); // reuse growable array for next time. + NOT_PRODUCT(_is_active = false;) +} + +// Record which objects are marked so we can unmark the same objects. +void MetadataOnStackMark::record(Metadata* m) { + assert(_is_active, "metadata on stack marking is active"); + _marked_objects->push(m); +} diff --git a/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp b/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp new file mode 100644 index 00000000000..5a4fda2f332 --- /dev/null +++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP +#define SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP + +#include "memory/allocation.hpp" + +class Metadata; + +// Helper class to mark and unmark metadata used on the stack as either handles +// or executing methods, so that it can't be deleted during class redefinition +// and class unloading. +// This is also used for other things that can be deallocated, like class +// metadata during parsing, relocated methods, and methods in backtraces. +class MetadataOnStackMark : public StackObj { + NOT_PRODUCT(static bool _is_active;) + public: + MetadataOnStackMark(); + ~MetadataOnStackMark(); + static void record(Metadata* m); +}; + +#endif // SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP diff --git a/hotspot/src/share/vm/classfile/placeholders.cpp b/hotspot/src/share/vm/classfile/placeholders.cpp index 1babaaf978c..10d7650db58 100644 --- a/hotspot/src/share/vm/classfile/placeholders.cpp +++ b/hotspot/src/share/vm/classfile/placeholders.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,7 +142,7 @@ PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, } -// placeholder used to track class loading internal states +// placeholder is used to track class loading internal states // placeholder existence now for loading superclass/superinterface // superthreadQ tracks class circularity, while loading superclass/superinterface // loadInstanceThreadQ tracks load_instance_class calls @@ -153,15 +153,17 @@ PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, // All claimants remove SeenThread after completing action // On removal: if definer and all queues empty, remove entry // Note: you can be in both placeholders and systemDictionary -// see parse_stream for redefine classes // Therefore - must always check SD first // Ignores the case where entry is not found void PlaceholderTable::find_and_remove(int index, unsigned int hash, - Symbol* name, ClassLoaderData* loader_data, Thread* thread) { + Symbol* name, ClassLoaderData* loader_data, + classloadAction action, + Thread* thread) { assert_locked_or_safepoint(SystemDictionary_lock); PlaceholderEntry *probe = get_entry(index, hash, name, loader_data); if (probe != NULL) { - // No other threads using this entry + probe->remove_seen_thread(thread, action); + // If no other threads using this entry, and this thread is not using this entry for other states if ((probe->superThreadQ() == NULL) && (probe->loadInstanceThreadQ() == NULL) && (probe->defineThreadQ() == NULL) && (probe->definer() == NULL)) { remove_entry(index, hash, name, loader_data); diff --git a/hotspot/src/share/vm/classfile/placeholders.hpp b/hotspot/src/share/vm/classfile/placeholders.hpp index af4518a462f..ca0d85af0fb 100644 --- a/hotspot/src/share/vm/classfile/placeholders.hpp +++ b/hotspot/src/share/vm/classfile/placeholders.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,7 +82,7 @@ public: }; // find_and_add returns probe pointer - old or new - // If no entry exists, add a placeholder entry and push SeenThread + // If no entry exists, add a placeholder entry and push SeenThread for classloadAction // If entry exists, reuse entry and push SeenThread for classloadAction PlaceholderEntry* find_and_add(int index, unsigned int hash, Symbol* name, ClassLoaderData* loader_data, @@ -92,9 +92,11 @@ public: void remove_entry(int index, unsigned int hash, Symbol* name, ClassLoaderData* loader_data); -// Remove placeholder information + // find_and_remove first removes SeenThread for classloadAction + // If all queues are empty and definer is null, remove the PlacheholderEntry completely void find_and_remove(int index, unsigned int hash, - Symbol* name, ClassLoaderData* loader_data, Thread* thread); + Symbol* name, ClassLoaderData* loader_data, + classloadAction action, Thread* thread); // GC support. void classes_do(KlassClosure* f); diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.hpp b/hotspot/src/share/vm/classfile/stackMapFrame.hpp index 3329f7a9e8b..bdeb956ba68 100644 --- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp +++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp @@ -178,7 +178,7 @@ class StackMapFrame : public ResourceObj { #ifdef DEBUG // Put bogus type to indicate it's no longer valid. if (_stack_mark != -1) { - for (int i = _stack_mark; i >= _stack_size; --i) { + for (int i = _stack_mark - 1; i >= _stack_size; --i) { _stack[i] = VerificationType::bogus_type(); } } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index a493e73d84d..a7370fcce29 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,7 +172,7 @@ Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, Handle assert(klass_h() == NULL, "Should not have result with exception pending"); Handle e(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; - THROW_MSG_CAUSE_0(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e); + THROW_MSG_CAUSE_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e); } else { return NULL; } @@ -181,9 +181,9 @@ Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name, Handle if (klass_h() == NULL) { ResourceMark rm(THREAD); if (throw_error) { - THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string()); + THROW_MSG_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string()); } else { - THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string()); + THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string()); } } return (Klass*)klass_h(); @@ -343,29 +343,29 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name, } if (throw_circularity_error) { ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_ClassCircularityError(), child_name->as_C_string()); + THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), child_name->as_C_string()); } // java.lang.Object should have been found above assert(class_name != NULL, "null super class for resolving"); // Resolve the super class or interface, check results on return - Klass* superk = NULL; - superk = SystemDictionary::resolve_or_null(class_name, + Klass* superk = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, THREAD); KlassHandle superk_h(THREAD, superk); - // Note: clean up of placeholders currently in callers of - // resolve_super_or_fail - either at update_dictionary time - // or on error + // Clean up of placeholders moved so that each classloadAction registrar self-cleans up + // It is no longer necessary to keep the placeholder table alive until update_dictionary + // or error. GC used to walk the placeholder table as strong roots. + // The instanceKlass is kept alive because the class loader is on the stack, + // which keeps the loader_data alive, as well as all instanceKlasses in + // the loader_data. parseClassFile adds the instanceKlass to loader_data. { - MutexLocker mu(SystemDictionary_lock, THREAD); - PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, child_name, loader_data); - if (probe != NULL) { - probe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER); - } + MutexLocker mu(SystemDictionary_lock, THREAD); + placeholders()->find_and_remove(p_index, p_hash, child_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD); + SystemDictionary_lock->notify_all(); } if (HAS_PENDING_EXCEPTION || superk_h() == NULL) { // can null superk @@ -430,8 +430,8 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, // We're using a No_Safepoint_Verifier to catch any place where we // might potentially do a GC at all. - // SystemDictionary::do_unloading() asserts that classes are only - // unloaded at a safepoint. + // Dictionary::do_unloading() asserts that classes in SD are only + // unloaded at a safepoint. Anonymous classes are not in SD. No_Safepoint_Verifier nosafepoint; dictionary()->add_protection_domain(d_index, d_hash, klass, loader_data, protection_domain, THREAD); @@ -486,7 +486,6 @@ void SystemDictionary::double_lock_wait(Handle lockObject, TRAPS) { // super class loading here. // This also is critical in cases where the original thread gets stalled // even in non-circularity situations. -// Note: only one thread can define the class, but multiple can resolve // Note: must call resolve_super_or_fail even if null super - // to force placeholder entry creation for this class for circularity detection // Caller must check for pending exception @@ -518,14 +517,6 @@ instanceKlassHandle SystemDictionary::handle_parallel_super_load( protection_domain, true, CHECK_(nh)); - // We don't redefine the class, so we just need to clean up if there - // was not an error (don't want to modify any system dictionary - // data structures). - { - MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } // parallelCapable class loaders do NOT wait for parallel superclass loads to complete // Serial class loaders and bootstrap classloader do wait for superclass loads @@ -595,6 +586,10 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // Do lookup to see if class already exist and the protection domain // has the right access + // This call uses find which checks protection domain already matches + // All subsequent calls use find_class, and set has_loaded_class so that + // before we return a result we call out to java to check for valid protection domain + // to allow returning the Klass* and add it to the pd_set if it is valid unsigned int d_hash = dictionary()->compute_hash(name, loader_data); int d_index = dictionary()->hash_to_index(d_hash); Klass* probe = dictionary()->find(d_index, d_hash, name, loader_data, @@ -652,7 +647,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } - // If the class in is in the placeholder table, class loading is in progress + // If the class is in the placeholder table, class loading is in progress if (super_load_in_progress && havesupername==true) { k = SystemDictionary::handle_parallel_super_load(name, superclassname, class_loader, protection_domain, lockObject, THREAD); @@ -664,7 +659,9 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } + bool throw_circularity_error = false; if (!class_has_been_loaded) { + bool load_instance_added = false; // add placeholder entry to record loading instance class // Five cases: @@ -690,7 +687,7 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // No performance benefit and no deadlock issues. // case 5. parallelCapable user level classloaders - without objectLocker // Allow parallel classloading of a class/classloader pair - bool throw_circularity_error = false; + { MutexLocker mu(SystemDictionary_lock, THREAD); if (class_loader.is_null() || !is_parallelCapable(class_loader)) { @@ -726,12 +723,13 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } } - // All cases: add LOAD_INSTANCE + // All cases: add LOAD_INSTANCE holding SystemDictionary_lock // case 3: UnsyncloadClass || case 5: parallelCapable: allow competing threads to try // LOAD_INSTANCE in parallel - // add placeholder entry even if error - callers will remove on error + if (!throw_circularity_error && !class_has_been_loaded) { PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, NULL, THREAD); + load_instance_added = true; // For class loaders that do not acquire the classloader object lock, // if they did not catch another thread holding LOAD_INSTANCE, // need a check analogous to the acquire ObjectLocker/find_class @@ -740,19 +738,18 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // class loaders holding the ObjectLock shouldn't find the class here Klass* check = find_class(d_index, d_hash, name, loader_data); if (check != NULL) { - // Klass is already loaded, so just return it + // Klass is already loaded, so return it after checking/adding protection domain k = instanceKlassHandle(THREAD, check); class_has_been_loaded = true; - newprobe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); } } } + // must throw error outside of owning lock if (throw_circularity_error) { + assert(!HAS_PENDING_EXCEPTION && load_instance_added == false,"circularity error cleanup"); ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_ClassCircularityError(), name->as_C_string()); + THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), name->as_C_string()); } if (!class_has_been_loaded) { @@ -782,20 +779,6 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } - // clean up placeholder entries for success or error - // This cleans up LOAD_INSTANCE entries - // It also cleans up LOAD_SUPER entries on errors from - // calling load_instance_class - { - MutexLocker mu(SystemDictionary_lock, THREAD); - PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, name, loader_data); - if (probe != NULL) { - probe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } - } - // If everything was OK (no exceptions, no null return value), and // class_loader is NOT the defining loader, do a little more bookkeeping. if (!HAS_PENDING_EXCEPTION && !k.is_null() && @@ -819,18 +802,22 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla } } } - if (HAS_PENDING_EXCEPTION || k.is_null()) { - // On error, clean up placeholders - { - MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } - return NULL; - } + } // load_instance_class loop + + if (load_instance_added == true) { + // clean up placeholder entries for LOAD_INSTANCE success or error + // This brackets the SystemDictionary updates for both defining + // and initiating loaders + MutexLocker mu(SystemDictionary_lock, THREAD); + placeholders()->find_and_remove(p_index, p_hash, name, loader_data, PlaceholderTable::LOAD_INSTANCE, THREAD); + SystemDictionary_lock->notify_all(); } } + if (HAS_PENDING_EXCEPTION || k.is_null()) { + return NULL; + } + #ifdef ASSERT { ClassLoaderData* loader_data = k->class_loader_data(); @@ -850,8 +837,8 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // so we cannot allow GC to occur while we're holding this entry. // We're using a No_Safepoint_Verifier to catch any place where we // might potentially do a GC at all. - // SystemDictionary::do_unloading() asserts that classes are only - // unloaded at a safepoint. + // Dictionary::do_unloading() asserts that classes in SD are only + // unloaded at a safepoint. Anonymous classes are not in SD. No_Safepoint_Verifier nosafepoint; if (dictionary()->is_valid_protection_domain(d_index, d_hash, name, loader_data, @@ -898,8 +885,8 @@ Klass* SystemDictionary::find(Symbol* class_name, // so we cannot allow GC to occur while we're holding this entry. // We're using a No_Safepoint_Verifier to catch any place where we // might potentially do a GC at all. - // SystemDictionary::do_unloading() asserts that classes are only - // unloaded at a safepoint. + // Dictionary::do_unloading() asserts that classes in SD are only + // unloaded at a safepoint. Anonymous classes are not in SD. No_Safepoint_Verifier nosafepoint; return dictionary()->find(d_index, d_hash, class_name, loader_data, protection_domain, THREAD); @@ -965,10 +952,6 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, // throw potential ClassFormatErrors. // // Note: "name" is updated. - // Further note: a placeholder will be added for this class when - // super classes are loaded (resolve_super_or_fail). We expect this - // to be called for all classes but java.lang.Object; and we preload - // java.lang.Object through resolve_or_fail, not this path. instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, loader_data, @@ -979,21 +962,6 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, true, THREAD); - // We don't redefine the class, so we just need to clean up whether there - // was an error or not (don't want to modify any system dictionary - // data structures). - // Parsed name could be null if we threw an error before we got far - // enough along to parse it -- in that case, there is nothing to clean up. - if (parsed_name != NULL) { - unsigned int p_hash = placeholders()->compute_hash(parsed_name, - loader_data); - int p_index = placeholders()->hash_to_index(p_hash); - { - MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, parsed_name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } - } if (host_klass.not_null() && k.not_null()) { assert(EnableInvokeDynamic, ""); @@ -1062,10 +1030,6 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, // throw potential ClassFormatErrors. // // Note: "name" is updated. - // Further note: a placeholder will be added for this class when - // super classes are loaded (resolve_super_or_fail). We expect this - // to be called for all classes but java.lang.Object; and we preload - // java.lang.Object through resolve_or_fail, not this path. instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, loader_data, @@ -1114,25 +1078,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, } } - // If parsing the class file or define_instance_class failed, we - // need to remove the placeholder added on our behalf. But we - // must make sure parsed_name is valid first (it won't be if we had - // a format error before the class was parsed far enough to - // find the name). - if (HAS_PENDING_EXCEPTION && parsed_name != NULL) { - unsigned int p_hash = placeholders()->compute_hash(parsed_name, - loader_data); - int p_index = placeholders()->hash_to_index(p_hash); - { - MutexLocker mu(SystemDictionary_lock, THREAD); - placeholders()->find_and_remove(p_index, p_hash, parsed_name, loader_data, THREAD); - SystemDictionary_lock->notify_all(); - } - return NULL; - } - - // Make sure that we didn't leave a place holder in the - // SystemDictionary; this is only done on success + // Make sure we have an entry in the SystemDictionary on success debug_only( { if (!HAS_PENDING_EXCEPTION) { assert(parsed_name != NULL, "parsed_name is still null?"); @@ -1253,66 +1199,6 @@ instanceKlassHandle SystemDictionary::load_shared_class( return ik; } -#ifdef KERNEL -// Some classes on the bootstrap class path haven't been installed on the -// system yet. Call the DownloadManager method to make them appear in the -// bootstrap class path and try again to load the named class. -// Note that with delegation class loaders all classes in another loader will -// first try to call this so it'd better be fast!! -static instanceKlassHandle download_and_retry_class_load( - Symbol* class_name, - TRAPS) { - - Klass* dlm = SystemDictionary::DownloadManager_klass(); - instanceKlassHandle nk; - - // If download manager class isn't loaded just return. - if (dlm == NULL) return nk; - - { HandleMark hm(THREAD); - ResourceMark rm(THREAD); - Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nk)); - Handle class_string = java_lang_String::externalize_classname(s, CHECK_(nk)); - - // return value - JavaValue result(T_OBJECT); - - // Call the DownloadManager. We assume that it has a lock because - // multiple classes could be not found and downloaded at the same time. - // class sun.misc.DownloadManager; - // public static String getBootClassPathEntryForClass(String className); - JavaCalls::call_static(&result, - KlassHandle(THREAD, dlm), - vmSymbols::getBootClassPathEntryForClass_name(), - vmSymbols::string_string_signature(), - class_string, - CHECK_(nk)); - - // Get result.string and add to bootclasspath - assert(result.get_type() == T_OBJECT, "just checking"); - oop obj = (oop) result.get_jobject(); - if (obj == NULL) { return nk; } - - Handle h_obj(THREAD, obj); - char* new_class_name = java_lang_String::as_platform_dependent_str(h_obj, - CHECK_(nk)); - - // lock the loader - // we use this lock because JVMTI does. - Handle loader_lock(THREAD, SystemDictionary::system_loader_lock()); - - ObjectLocker ol(loader_lock, THREAD); - // add the file to the bootclasspath - ClassLoader::update_class_path_entry_list(new_class_name, true); - } // end HandleMark - - if (TraceClassLoading) { - ClassLoader::print_bootclasspath(); - } - return ClassLoader::load_classfile(class_name, CHECK_(nk)); -} -#endif // KERNEL - instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle @@ -1332,15 +1218,6 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha k = ClassLoader::load_classfile(class_name, CHECK_(nh)); } -#ifdef KERNEL - // If the VM class loader has failed to load the class, call the - // DownloadManager class to make it magically appear on the classpath - // and try again. This is only configured with the Kernel VM. - if (k.is_null()) { - k = download_and_retry_class_load(class_name, CHECK_(nh)); - } -#endif // KERNEL - // find_or_define_instance_class may return a different InstanceKlass if (!k.is_null()) { k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh)); @@ -1547,8 +1424,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas // Other cases fall through, and may run into duplicate defines // caught by finding an entry in the SystemDictionary if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instance_klass() != NULL)) { - probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); - placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, THREAD); + placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); SystemDictionary_lock->notify_all(); #ifdef ASSERT Klass* check = find_class(d_index, d_hash, name_h, loader_data); @@ -1578,8 +1454,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas probe->set_instance_klass(k()); } probe->set_definer(NULL); - probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); - placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, THREAD); + placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD); SystemDictionary_lock->notify_all(); } } @@ -1736,6 +1611,8 @@ int SystemDictionary::calculate_systemdictionary_size(int classcount) { } return newsize; } +// Assumes classes in the SystemDictionary are only unloaded at a safepoint +// Note: anonymous classes are not in the SD. bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) { // First, mark for unload all ClassLoaderData referencing a dead class loader. bool has_dead_loaders = ClassLoaderDataGraph::do_unloading(is_alive); @@ -1876,13 +1753,7 @@ bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) { Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid); Klass** klassp = &_well_known_klasses[id]; bool must_load = (init_opt < SystemDictionary::Opt); - bool try_load = true; - if (init_opt == SystemDictionary::Opt_Kernel) { -#ifndef KERNEL - try_load = false; -#endif //KERNEL - } - if ((*klassp) == NULL && try_load) { + if ((*klassp) == NULL) { if (must_load) { (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class } else { @@ -1972,12 +1843,6 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { //_box_klasses[T_OBJECT] = WK_KLASS(object_klass); //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); -#ifdef KERNEL - if (DownloadManager_klass() == NULL) { - warning("Cannot find sun/jkernel/DownloadManager"); - } -#endif // KERNEL - { // Compute whether we should use loadClass or loadClassInternal when loading classes. Method* method = InstanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); _has_loadClassInternal = (method != NULL); @@ -2105,9 +1970,7 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, // All loaded classes get a unique ID. TRACE_INIT_ID(k); - // Check for a placeholder. If there, remove it and make a - // new system dictionary entry. - placeholders()->find_and_remove(p_index, p_hash, name, loader_data, THREAD); + // Make a new system dictionary entry. Klass* sd_check = find_class(d_index, d_hash, name, loader_data); if (sd_check == NULL) { dictionary()->add_klass(name, loader_data, k); @@ -2116,12 +1979,8 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, #ifdef ASSERT sd_check = find_class(d_index, d_hash, name, loader_data); assert (sd_check != NULL, "should have entry in system dictionary"); -// Changed to allow PH to remain to complete class circularity checking -// while only one thread can define a class at one time, multiple -// classes can resolve the superclass for a class at one time, -// and the placeholder is used to track that -// Symbol* ph_check = find_placeholder(name, class_loader); -// assert (ph_check == NULL, "should not have a placeholder entry"); + // Note: there may be a placeholder entry: for circularity testing + // or for parallel defines #endif SystemDictionary_lock->notify_all(); } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index e2f660ee171..d415c9b1e4f 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -168,8 +168,6 @@ class SymbolPropertyTable; /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \ \ - do_klass(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel ) \ - \ do_klass(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt ) \ \ /* Preload boxing klasses */ \ @@ -211,7 +209,6 @@ class SystemDictionary : AllStatic { Opt, // preload tried; NULL if not present Opt_Only_JDK14NewRef, // preload tried; use only with NewReflection Opt_Only_JDK15, // preload tried; use only with JDK1.5+ - Opt_Kernel, // preload tried only #ifdef KERNEL OPTION_LIMIT, CEIL_LG_OPTION_LIMIT = 4 // OPTION_LIMIT <= (1<") \ template(class_initializer_name, "") \ @@ -383,7 +385,6 @@ template(basicType_name, "basicType") \ template(append_name, "append") \ template(klass_name, "klass") \ - template(resolved_constructor_name, "resolved_constructor") \ template(array_klass_name, "array_klass") \ template(oop_size_name, "oop_size") \ template(static_oop_field_count_name, "static_oop_field_count") \ @@ -733,6 +734,11 @@ do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \ do_name( checkIndex_name, "checkIndex") \ \ + do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ + do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ + do_name( encodeISOArray_name, "encodeISOArray") \ + do_signature(encodeISOArray_signature, "([CI[BII)I") \ + \ /* java/lang/ref/Reference */ \ do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ \ diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index c40a377ebb3..d5b8f8f9a78 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -30,6 +30,7 @@ #include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "code/pcDesc.hpp" +#include "compiler/compileBroker.hpp" #include "gc_implementation/shared/markSweep.hpp" #include "memory/allocation.inline.hpp" #include "memory/gcLocker.hpp" @@ -39,6 +40,7 @@ #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/arguments.hpp" #include "runtime/icache.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" @@ -168,6 +170,8 @@ nmethod* CodeCache::next_nmethod (CodeBlob* cb) { return (nmethod*)cb; } +static size_t maxCodeCacheUsed = 0; + CodeBlob* CodeCache::allocate(int size) { // Do not seize the CodeCache lock here--if the caller has not // already done so, we are going to lose bigtime, since the code @@ -192,6 +196,8 @@ CodeBlob* CodeCache::allocate(int size) { (address)_heap->end() - (address)_heap->begin()); } } + maxCodeCacheUsed = MAX2(maxCodeCacheUsed, ((address)_heap->high_boundary() - + (address)_heap->low_boundary()) - unallocated_capacity()); verify_if_often(); print_trace("allocation", cb, size); return cb; @@ -928,7 +934,14 @@ void CodeCache::print_internals() { FREE_C_HEAP_ARRAY(int, buckets, mtCode); } +#endif // !PRODUCT + void CodeCache::print() { + print_summary(tty); + +#ifndef PRODUCT + if (!Verbose) return; + CodeBlob_sizes live; CodeBlob_sizes dead; @@ -953,7 +966,7 @@ void CodeCache::print() { } - if (Verbose) { + if (WizardMode) { // print the oop_map usage int code_size = 0; int number_of_blobs = 0; @@ -977,20 +990,30 @@ void CodeCache::print() { tty->print_cr(" map size = %d", map_size); } +#endif // !PRODUCT } -#endif // PRODUCT +void CodeCache::print_summary(outputStream* st, bool detailed) { + size_t total = (_heap->high_boundary() - _heap->low_boundary()); + st->print_cr("CodeCache: size=" SIZE_FORMAT "Kb used=" SIZE_FORMAT + "Kb max_used=" SIZE_FORMAT "Kb free=" SIZE_FORMAT + "Kb max_free_chunk=" SIZE_FORMAT "Kb", + total/K, (total - unallocated_capacity())/K, + maxCodeCacheUsed/K, unallocated_capacity()/K, largest_free_block()/K); -void CodeCache::print_bounds(outputStream* st) { - st->print_cr("Code Cache [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")", - _heap->low_boundary(), - _heap->high(), - _heap->high_boundary()); - st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT - " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT "Kb" - " largest_free_block=" SIZE_FORMAT, - nof_blobs(), nof_nmethods(), nof_adapters(), - unallocated_capacity()/K, largest_free_block()); + if (detailed) { + st->print_cr(" bounds [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT "]", + _heap->low_boundary(), + _heap->high(), + _heap->high_boundary()); + st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT + " adapters=" UINT32_FORMAT, + nof_blobs(), nof_nmethods(), nof_adapters()); + st->print_cr(" compilation: %s", CompileBroker::should_compile_new_jobs() ? + "enabled" : Arguments::mode() == Arguments::_int ? + "disabled (interpreter mode)" : + "disabled (not enough contiguous free space left)"); + } } void CodeCache::log_state(outputStream* st) { diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp index 6187ba9a2a7..92ce241b938 100644 --- a/hotspot/src/share/vm/code/codeCache.hpp +++ b/hotspot/src/share/vm/code/codeCache.hpp @@ -145,11 +145,11 @@ class CodeCache : AllStatic { static void prune_scavenge_root_nmethods(); // Printing/debugging - static void print() PRODUCT_RETURN; // prints summary + static void print(); // prints summary static void print_internals(); static void verify(); // verifies the code cache static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN; - static void print_bounds(outputStream* st); // Prints a summary of the bounds of the code cache + static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage static void log_state(outputStream* st); // The full limits of the codeCache diff --git a/hotspot/src/share/vm/compiler/abstractCompiler.hpp b/hotspot/src/share/vm/compiler/abstractCompiler.hpp index 9007a82fc49..96453e7d9ba 100644 --- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp +++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp @@ -50,6 +50,7 @@ class AbstractCompiler : public CHeapObj { // Missing feature tests virtual bool supports_native() { return true; } virtual bool supports_osr () { return true; } + virtual bool can_compile_method(methodHandle method) { return true; } #if defined(TIERED) || ( !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK)) virtual bool is_c1 () { return false; } virtual bool is_c2 () { return false; } diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 73ab865dc74..6f4e671c165 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1218,7 +1218,7 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, // lock, make sure that the compilation // isn't prohibited in a straightforward way. - if (compiler(comp_level) == NULL || compilation_is_prohibited(method, osr_bci, comp_level)) { + if (compiler(comp_level) == NULL || !compiler(comp_level)->can_compile_method(method) || compilation_is_prohibited(method, osr_bci, comp_level)) { return NULL; } @@ -1398,7 +1398,7 @@ bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, method->print_short_name(tty); tty->cr(); } - method->set_not_compilable_quietly(); + method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompilerOracle"); } return false; @@ -1714,6 +1714,20 @@ void CompileBroker::maybe_block() { } } +// wrapper for CodeCache::print_summary() +static void codecache_print(bool detailed) +{ + ResourceMark rm; + stringStream s; + // Dump code cache into a buffer before locking the tty, + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + CodeCache::print_summary(&s, detailed); + } + ttyLocker ttyl; + tty->print_cr(s.as_string()); +} + // ------------------------------------------------------------------ // CompileBroker::invoke_compiler_on_method // @@ -1841,6 +1855,9 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { tty->print_cr("size: %d time: %d inlined: %d bytes", code_size, (int)time.milliseconds(), task->num_inlined_bytecodes()); } + if (PrintCodeCacheOnCompilation) + codecache_print(/* detailed= */ false); + // Disable compilation, if required. switch (compilable) { case ciEnv::MethodCompilable_never: @@ -1885,6 +1902,7 @@ void CompileBroker::handle_full_code_cache() { UseInterpreter = true; if (UseCompiler || AlwaysCompileLoopMethods ) { if (xtty != NULL) { + ResourceMark rm; stringStream s; // Dump code cache state into a buffer before locking the tty, // because log_state() will use locks causing lock conflicts. @@ -1898,9 +1916,9 @@ void CompileBroker::handle_full_code_cache() { } warning("CodeCache is full. Compiler has been disabled."); warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); - CodeCache::print_bounds(tty); #ifndef PRODUCT if (CompileTheWorld || ExitOnFullCodeCache) { + codecache_print(/* detailed= */ true); before_exit(JavaThread::current()); exit_globals(); // will delete tty vm_direct_exit(CompileTheWorld ? 0 : 1); @@ -1913,6 +1931,7 @@ void CompileBroker::handle_full_code_cache() { AlwaysCompileLoopMethods = false; } } + codecache_print(/* detailed= */ true); } // ------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/compiler/oopMap.cpp b/hotspot/src/share/vm/compiler/oopMap.cpp index 7c51c669b5c..8e6834c710d 100644 --- a/hotspot/src/share/vm/compiler/oopMap.cpp +++ b/hotspot/src/share/vm/compiler/oopMap.cpp @@ -542,17 +542,17 @@ void print_register_type(OopMapValue::oop_types x, VMReg optional, st->print("Oop"); break; case OopMapValue::value_value: - st->print("Value" ); + st->print("Value"); break; case OopMapValue::narrowoop_value: - tty->print("NarrowOop" ); + st->print("NarrowOop"); break; case OopMapValue::callee_saved_value: - st->print("Callers_" ); + st->print("Callers_"); optional->print_on(st); break; case OopMapValue::derived_oop_value: - st->print("Derived_oop_" ); + st->print("Derived_oop_"); optional->print_on(st); break; default: diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 45e53170859..cb8b73743e1 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -102,7 +102,7 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // temporarily disabled). switch (dictionaryChoice) { case FreeBlockDictionary::dictionaryBinaryTree: - _dictionary = new BinaryTreeDictionary(mr); + _dictionary = new AFLBinaryTreeDictionary(mr); break; case FreeBlockDictionary::dictionarySplayTree: case FreeBlockDictionary::dictionarySkipList: @@ -122,7 +122,8 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // moved to its new location before the klass is moved. // Set the _refillSize for the linear allocation blocks if (!use_adaptive_freelists) { - FreeChunk* fc = _dictionary->get_chunk(mr.word_size()); + FreeChunk* fc = _dictionary->get_chunk(mr.word_size(), + FreeBlockDictionary::atLeast); // The small linAB initially has all the space and will allocate // a chunk of any size. HeapWord* addr = (HeapWord*) fc; @@ -554,7 +555,7 @@ void CompactibleFreeListSpace::reportFreeListStatistics() const { reportIndexedFreeListStatistics(); size_t total_size = totalSizeInIndexedFreeLists() + _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); - gclog_or_tty->print(" free=%ld frag=%1.4f\n", total_size, flsFrag()); + gclog_or_tty->print(" free=" SIZE_FORMAT " frag=%1.4f\n", total_size, flsFrag()); } } @@ -1647,7 +1648,8 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size, FreeChunk* CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { assert_locked(); - FreeChunk* fc = _dictionary->get_chunk(size); + FreeChunk* fc = _dictionary->get_chunk(size, + FreeBlockDictionary::atLeast); if (fc == NULL) { return NULL; } @@ -1664,7 +1666,8 @@ CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { FreeChunk* CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { assert_locked(); - FreeChunk* fc = _dictionary->get_chunk(size); + FreeChunk* fc = _dictionary->get_chunk(size, + FreeBlockDictionary::atLeast); if (fc == NULL) { return fc; } @@ -1677,7 +1680,8 @@ CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { if (fc->size() < size + MinChunkSize) { // Return the chunk to the dictionary and go get a bigger one. returnChunkToDictionary(fc); - fc = _dictionary->get_chunk(size + MinChunkSize); + fc = _dictionary->get_chunk(size + MinChunkSize, + FreeBlockDictionary::atLeast); if (fc == NULL) { return NULL; } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 1b3d93ed248..23c95897cfa 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -131,7 +131,7 @@ class CompactibleFreeListSpace: public CompactibleSpace { LinearAllocBlock _smallLinearAllocBlock; FreeBlockDictionary::DictionaryChoice _dictionaryChoice; - FreeBlockDictionary* _dictionary; // ptr to dictionary for large size blocks + AFLBinaryTreeDictionary* _dictionary; // ptr to dictionary for large size blocks AdaptiveFreeList _indexedFreeList[IndexSetSize]; // indexed array for small size blocks diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 25b936fd8a9..6c1de182b74 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -3338,7 +3338,7 @@ bool ConcurrentMarkSweepGeneration::grow_by(size_t bytes) { if (Verbose && PrintGC) { size_t new_mem_size = _virtual_space.committed_size(); size_t old_mem_size = new_mem_size - bytes; - gclog_or_tty->print_cr("Expanding %s from %ldK by %ldK to %ldK", + gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", name(), old_mem_size/K, bytes/K, new_mem_size/K); } } @@ -9203,7 +9203,7 @@ void ASConcurrentMarkSweepGeneration::shrink_by(size_t desired_bytes) { if (Verbose && PrintGCDetails) { size_t new_mem_size = _virtual_space.committed_size(); size_t old_mem_size = new_mem_size + bytes; - gclog_or_tty->print_cr("Shrinking %s from %ldK by %ldK to %ldK", + gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", name(), old_mem_size/K, bytes/K, new_mem_size/K); } } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp index a67e19d89d2..1a46ed3f52d 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -25,8 +25,6 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP -typedef BinaryTreeDictionary AFLBinaryTreeDictionary; - #define VM_STRUCTS_CMS(nonstatic_field, \ volatile_nonstatic_field, \ static_field) \ @@ -34,14 +32,15 @@ typedef BinaryTreeDictionary AFLBinaryTreeDictionar nonstatic_field(CompactibleFreeListSpace, _bt, BlockOffsetArrayNonContigSpace) \ \ nonstatic_field(CMSBitMap, _bmWordSize, size_t) \ - nonstatic_field(CMSBitMap, _shifter, const int) \ - nonstatic_field(CMSBitMap, _bm, BitMap) \ - nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \ + nonstatic_field(CMSBitMap, _shifter, const int) \ + nonstatic_field(CMSBitMap, _bm, BitMap) \ + nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \ nonstatic_field(CMSCollector, _markBitMap, CMSBitMap) \ nonstatic_field(ConcurrentMarkSweepGeneration, _cmsSpace, CompactibleFreeListSpace*) \ static_field(ConcurrentMarkSweepThread, _collector, CMSCollector*) \ nonstatic_field(LinearAllocBlock, _word_size, size_t) \ nonstatic_field(AFLBinaryTreeDictionary, _total_size, size_t) \ + nonstatic_field(CompactibleFreeListSpace, _dictionary, AFLBinaryTreeDictionary*) \ nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList) \ nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) @@ -62,10 +61,9 @@ typedef BinaryTreeDictionary AFLBinaryTreeDictionar declare_toplevel_type(SurrogateLockerThread*) \ declare_toplevel_type(CompactibleFreeListSpace*) \ declare_toplevel_type(CMSCollector*) \ - declare_toplevel_type(AFLBinaryTreeDictionary*) \ + declare_toplevel_type(AFLBinaryTreeDictionary) \ declare_toplevel_type(LinearAllocBlock) \ - declare_toplevel_type(FreeBlockDictionary) \ - declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary) + declare_toplevel_type(FreeBlockDictionary) #define VM_INT_CONSTANTS_CMS(declare_constant) \ declare_constant(Generation::ConcurrentMarkSweep) \ diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 3199cbf5a60..28c733c150f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -571,19 +571,14 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else { - if (ConcGCThreads > 0) { - // notice that ConcGCThreads overwrites G1MarkingOverheadPercent + if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) { + // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent // if both are set - - _parallel_marking_threads = (uint) ConcGCThreads; - _max_parallel_marking_threads = _parallel_marking_threads; _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else if (G1MarkingOverheadPercent > 0) { - // we will calculate the number of parallel marking threads - // based on a target overhead with respect to the soft real-time - // goal - + // We will calculate the number of parallel marking threads based + // on a target overhead with respect to the soft real-time goal double marking_overhead = (double) G1MarkingOverheadPercent / 100.0; double overall_cm_overhead = (double) MaxGCPauseMillis * marking_overhead / @@ -596,17 +591,22 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : double sleep_factor = (1.0 - marking_task_overhead) / marking_task_overhead; - _parallel_marking_threads = (uint) marking_thread_num; - _max_parallel_marking_threads = _parallel_marking_threads; + FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num); _sleep_factor = sleep_factor; _marking_task_overhead = marking_task_overhead; } else { - _parallel_marking_threads = scale_parallel_threads((uint)ParallelGCThreads); - _max_parallel_marking_threads = _parallel_marking_threads; + // Calculate the number of parallel marking threads by scaling + // the number of parallel GC threads. + uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads); + FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num); _sleep_factor = 0.0; _marking_task_overhead = 1.0; } + assert(ConcGCThreads > 0, "Should have been set"); + _parallel_marking_threads = (uint) ConcGCThreads; + _max_parallel_marking_threads = _parallel_marking_threads; + if (parallel_marking_threads() > 1) { _cleanup_task_overhead = 1.0; } else { @@ -1190,7 +1190,7 @@ void ConcurrentMark::scanRootRegions() { uint active_workers = MAX2(1U, parallel_marking_threads()); CMRootRegionScanTask task(this); - if (parallel_marking_threads() > 0) { + if (use_parallel_marking_threads()) { _parallel_workers->set_active_workers((int) active_workers); _parallel_workers->run_task(&task); } else { @@ -1226,7 +1226,7 @@ void ConcurrentMark::markFromRoots() { set_phase(active_workers, true /* concurrent */); CMConcurrentMarkingTask markingTask(this, cmThread()); - if (parallel_marking_threads() > 0) { + if (use_parallel_marking_threads()) { _parallel_workers->set_active_workers((int)active_workers); // Don't set _n_par_threads because it affects MT in proceess_strong_roots() // and the decisions on that MT processing is made elsewhere. @@ -2167,7 +2167,8 @@ void ConcurrentMark::completeCleanup() { assert(tmp_free_list.is_empty(), "post-condition"); } -// Support closures for reference procssing in G1 +// Supporting Object and Oop closures for reference discovery +// and processing in during marking bool G1CMIsAliveClosure::do_object_b(oop obj) { HeapWord* addr = (HeapWord*)obj; @@ -2175,73 +2176,26 @@ bool G1CMIsAliveClosure::do_object_b(oop obj) { (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); } -class G1CMKeepAliveClosure: public ExtendedOopClosure { - G1CollectedHeap* _g1; - ConcurrentMark* _cm; - public: - G1CMKeepAliveClosure(G1CollectedHeap* g1, ConcurrentMark* cm) : - _g1(g1), _cm(cm) { - assert(Thread::current()->is_VM_thread(), "otherwise fix worker id"); - } +// 'Keep Alive' oop closure used by both serial parallel reference processing. +// Uses the CMTask associated with a worker thread (for serial reference +// processing the CMTask for worker 0 is used) to preserve (mark) and +// trace referent objects. +// +// Using the CMTask and embedded local queues avoids having the worker +// threads operating on the global mark stack. This reduces the risk +// of overflowing the stack - which we would rather avoid at this late +// state. Also using the tasks' local queues removes the potential +// of the workers interfering with each other that could occur if +// operating on the global stack. - virtual void do_oop(narrowOop* p) { do_oop_work(p); } - virtual void do_oop( oop* p) { do_oop_work(p); } - - template void do_oop_work(T* p) { - oop obj = oopDesc::load_decode_heap_oop(p); - HeapWord* addr = (HeapWord*)obj; - - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[0] we're looking at location " - "*"PTR_FORMAT" = "PTR_FORMAT, - p, (void*) obj); - } - - if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) { - _cm->mark_and_count(obj); - _cm->mark_stack_push(obj); - } - } -}; - -class G1CMDrainMarkingStackClosure: public VoidClosure { - ConcurrentMark* _cm; - CMMarkStack* _markStack; - G1CMKeepAliveClosure* _oopClosure; - public: - G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMMarkStack* markStack, - G1CMKeepAliveClosure* oopClosure) : - _cm(cm), - _markStack(markStack), - _oopClosure(oopClosure) { } - - void do_void() { - _markStack->drain(_oopClosure, _cm->nextMarkBitMap(), false); - } -}; - -// 'Keep Alive' closure used by parallel reference processing. -// An instance of this closure is used in the parallel reference processing -// code rather than an instance of G1CMKeepAliveClosure. We could have used -// the G1CMKeepAliveClosure as it is MT-safe. Also reference objects are -// placed on to discovered ref lists once so we can mark and push with no -// need to check whether the object has already been marked. Using the -// G1CMKeepAliveClosure would mean, however, having all the worker threads -// operating on the global mark stack. This means that an individual -// worker would be doing lock-free pushes while it processes its own -// discovered ref list followed by drain call. If the discovered ref lists -// are unbalanced then this could cause interference with the other -// workers. Using a CMTask (and its embedded local data structures) -// avoids that potential interference. -class G1CMParKeepAliveAndDrainClosure: public OopClosure { +class G1CMKeepAliveAndDrainClosure: public OopClosure { ConcurrentMark* _cm; CMTask* _task; int _ref_counter_limit; int _ref_counter; public: - G1CMParKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task), - _ref_counter_limit(G1RefProcDrainInterval) { + G1CMKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) : + _cm(cm), _task(task), _ref_counter_limit(G1RefProcDrainInterval) { assert(_ref_counter_limit > 0, "sanity"); _ref_counter = _ref_counter_limit; } @@ -2262,18 +2216,22 @@ class G1CMParKeepAliveAndDrainClosure: public OopClosure { _ref_counter--; if (_ref_counter == 0) { - // We have dealt with _ref_counter_limit references, pushing them and objects - // reachable from them on to the local stack (and possibly the global stack). - // Call do_marking_step() to process these entries. We call the routine in a - // loop, which we'll exit if there's nothing more to do (i.e. we're done - // with the entries that we've pushed as a result of the deal_with_reference - // calls above) or we overflow. - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag - // while there may still be some work to do. (See the comment at the - // beginning of CMTask::do_marking_step() for those conditions - one of which - // is reaching the specified time target.) It is only when - // CMTask::do_marking_step() returns without setting the has_aborted() flag - // that the marking has completed. + // We have dealt with _ref_counter_limit references, pushing them + // and objects reachable from them on to the local stack (and + // possibly the global stack). Call CMTask::do_marking_step() to + // process these entries. + // + // We call CMTask::do_marking_step() in a loop, which we'll exit if + // there's nothing more to do (i.e. we're done with the entries that + // were pushed as a result of the CMTask::deal_with_reference() calls + // above) or we overflow. + // + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // flag while there may still be some work to do. (See the comment at + // the beginning of CMTask::do_marking_step() for those conditions - + // one of which is reaching the specified time target.) It is only + // when CMTask::do_marking_step() returns without setting the + // has_aborted() flag that the marking step has completed. do { double mark_step_duration_ms = G1ConcMarkStepDurationMillis; _task->do_marking_step(mark_step_duration_ms, @@ -2290,36 +2248,59 @@ class G1CMParKeepAliveAndDrainClosure: public OopClosure { } }; -class G1CMParDrainMarkingStackClosure: public VoidClosure { +// 'Drain' oop closure used by both serial and parallel reference processing. +// Uses the CMTask associated with a given worker thread (for serial +// reference processing the CMtask for worker 0 is used). Calls the +// do_marking_step routine, with an unbelievably large timeout value, +// to drain the marking data structures of the remaining entries +// added by the 'keep alive' oop closure above. + +class G1CMDrainMarkingStackClosure: public VoidClosure { ConcurrentMark* _cm; - CMTask* _task; + CMTask* _task; + bool _do_stealing; + bool _do_termination; public: - G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task) { } + G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task, bool is_par) : + _cm(cm), _task(task) { + assert(is_par || _task->worker_id() == 0, + "Only task for worker 0 should be used if ref processing is single threaded"); + // We only allow stealing and only enter the termination protocol + // in CMTask::do_marking_step() if this closure is being instantiated + // for parallel reference processing. + _do_stealing = _do_termination = is_par; + } void do_void() { do { if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[%u] Drain: Calling do marking_step", - _task->worker_id()); + gclog_or_tty->print_cr("\t[%u] Drain: Calling do_marking_step - " + "stealing: %s, termination: %s", + _task->worker_id(), + BOOL_TO_STR(_do_stealing), + BOOL_TO_STR(_do_termination)); } - // We call CMTask::do_marking_step() to completely drain the local and - // global marking stacks. The routine is called in a loop, which we'll - // exit if there's nothing more to do (i.e. we'completely drained the - // entries that were pushed as a result of applying the - // G1CMParKeepAliveAndDrainClosure to the entries on the discovered ref - // lists above) or we overflow the global marking stack. - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag - // while there may still be some work to do. (See the comment at the - // beginning of CMTask::do_marking_step() for those conditions - one of which - // is reaching the specified time target.) It is only when - // CMTask::do_marking_step() returns without setting the has_aborted() flag - // that the marking has completed. + // We call CMTask::do_marking_step() to completely drain the local + // and global marking stacks of entries pushed by the 'keep alive' + // oop closure (an instance of G1CMKeepAliveAndDrainClosure above). + // + // CMTask::do_marking_step() is called in a loop, which we'll exit + // if there's nothing more to do (i.e. we'completely drained the + // entries that were pushed as a a result of applying the 'keep alive' + // closure to the entries on the discovered ref lists) or we overflow + // the global marking stack. + // + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // flag while there may still be some work to do. (See the comment at + // the beginning of CMTask::do_marking_step() for those conditions - + // one of which is reaching the specified time target.) It is only + // when CMTask::do_marking_step() returns without setting the + // has_aborted() flag that the marking step has completed. _task->do_marking_step(1000000000.0 /* something very large */, - true /* do_stealing */, - true /* do_termination */); + _do_stealing, + _do_termination); } while (_task->has_aborted() && !_cm->has_overflown()); } }; @@ -2352,19 +2333,23 @@ class G1CMRefProcTaskProxy: public AbstractGangTask { ProcessTask& _proc_task; G1CollectedHeap* _g1h; ConcurrentMark* _cm; + bool _processing_is_mt; public: G1CMRefProcTaskProxy(ProcessTask& proc_task, G1CollectedHeap* g1h, ConcurrentMark* cm) : AbstractGangTask("Process reference objects in parallel"), - _proc_task(proc_task), _g1h(g1h), _cm(cm) { } + _proc_task(proc_task), _g1h(g1h), _cm(cm) { + ReferenceProcessor* rp = _g1h->ref_processor_cm(); + _processing_is_mt = rp->processing_is_mt(); + } virtual void work(uint worker_id) { CMTask* marking_task = _cm->task(worker_id); G1CMIsAliveClosure g1_is_alive(_g1h); - G1CMParKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task); - G1CMParDrainMarkingStackClosure g1_par_drain(_cm, marking_task); + G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task); + G1CMDrainMarkingStackClosure g1_par_drain(_cm, marking_task, _processing_is_mt); _proc_task.work(worker_id, g1_is_alive, g1_par_keep_alive, g1_par_drain); } @@ -2372,6 +2357,7 @@ public: void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) { assert(_workers != NULL, "Need parallel worker threads."); + assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT"); G1CMRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm); @@ -2399,6 +2385,7 @@ public: void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) { assert(_workers != NULL, "Need parallel worker threads."); + assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT"); G1CMRefEnqueueTaskProxy enq_task_proxy(enq_task); @@ -2429,59 +2416,58 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { // See the comment in G1CollectedHeap::ref_processing_init() // about how reference processing currently works in G1. - // Process weak references. + // Set the soft reference policy rp->setup_policy(clear_all_soft_refs); assert(_markStack.isEmpty(), "mark stack should be empty"); - G1CMKeepAliveClosure g1_keep_alive(g1h, this); - G1CMDrainMarkingStackClosure - g1_drain_mark_stack(this, &_markStack, &g1_keep_alive); + // Non-MT instances 'Keep Alive' and 'Complete GC' oop closures. + G1CMKeepAliveAndDrainClosure g1_keep_alive(this, task(0)); + G1CMDrainMarkingStackClosure g1_drain_mark_stack(this, task(0), false); + + // We need at least one active thread. If reference processing is + // not multi-threaded we use the current (ConcurrentMarkThread) thread, + // otherwise we use the work gang from the G1CollectedHeap and we + // utilize all the worker threads we can. + uint active_workers = (rp->processing_is_mt() && g1h->workers() != NULL + ? g1h->workers()->active_workers() + : 1U); - // We use the work gang from the G1CollectedHeap and we utilize all - // the worker threads. - uint active_workers = g1h->workers() ? g1h->workers()->active_workers() : 1U; active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U); G1CMRefProcTaskExecutor par_task_executor(g1h, this, g1h->workers(), active_workers); - if (rp->processing_is_mt()) { - // Set the degree of MT here. If the discovery is done MT, there - // may have been a different number of threads doing the discovery - // and a different number of discovered lists may have Ref objects. - // That is OK as long as the Reference lists are balanced (see - // balance_all_queues() and balance_queues()). - rp->set_active_mt_degree(active_workers); + AbstractRefProcTaskExecutor* executor = (rp->processing_is_mt() + ? &par_task_executor + : NULL); - rp->process_discovered_references(&g1_is_alive, + // Set the degree of MT processing here. If the discovery was done MT, + // the number of threads involved during discovery could differ from + // the number of active workers. This is OK as long as the discovered + // Reference lists are balanced (see balance_all_queues() and balance_queues()). + rp->set_active_mt_degree(active_workers); + + // Process the weak references. + rp->process_discovered_references(&g1_is_alive, &g1_keep_alive, &g1_drain_mark_stack, - &par_task_executor); + executor); - // The work routines of the parallel keep_alive and drain_marking_stack - // will set the has_overflown flag if we overflow the global marking - // stack. - } else { - rp->process_discovered_references(&g1_is_alive, - &g1_keep_alive, - &g1_drain_mark_stack, - NULL); - } + // The do_oop work routines of the keep_alive and drain_marking_stack + // oop closures will set the has_overflown flag if we overflow the + // global marking stack. assert(_markStack.overflow() || _markStack.isEmpty(), "mark stack should be empty (unless it overflowed)"); if (_markStack.overflow()) { - // Should have been done already when we tried to push an + // This should have been done already when we tried to push an // entry on to the global mark stack. But let's do it again. set_has_overflown(); } - if (rp->processing_is_mt()) { - assert(rp->num_q() == active_workers, "why not"); - rp->enqueue_discovered_references(&par_task_executor); - } else { - rp->enqueue_discovered_references(); - } + assert(rp->num_q() == active_workers, "why not"); + + rp->enqueue_discovered_references(executor); rp->verify_no_references_recorded(); assert(!rp->discovery_enabled(), "Post condition"); @@ -3242,7 +3228,9 @@ void ConcurrentMark::print_summary_info() { } void ConcurrentMark::print_worker_threads_on(outputStream* st) const { - _parallel_workers->print_worker_threads_on(st); + if (use_parallel_marking_threads()) { + _parallel_workers->print_worker_threads_on(st); + } } // We take a break if someone is trying to stop the world. diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 34c5601e050..6ec27c7d9fa 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -371,8 +371,8 @@ class ConcurrentMark: public CHeapObj { friend class CalcLiveObjectsClosure; friend class G1CMRefProcTaskProxy; friend class G1CMRefProcTaskExecutor; - friend class G1CMParKeepAliveAndDrainClosure; - friend class G1CMParDrainMarkingStackClosure; + friend class G1CMKeepAliveAndDrainClosure; + friend class G1CMDrainMarkingStackClosure; protected: ConcurrentMarkThread* _cmThread; // the thread doing the work @@ -499,17 +499,26 @@ protected: } // accessor methods - uint parallel_marking_threads() { return _parallel_marking_threads; } - uint max_parallel_marking_threads() { return _max_parallel_marking_threads;} - double sleep_factor() { return _sleep_factor; } - double marking_task_overhead() { return _marking_task_overhead;} - double cleanup_sleep_factor() { return _cleanup_sleep_factor; } - double cleanup_task_overhead() { return _cleanup_task_overhead;} + uint parallel_marking_threads() const { return _parallel_marking_threads; } + uint max_parallel_marking_threads() const { return _max_parallel_marking_threads;} + double sleep_factor() { return _sleep_factor; } + double marking_task_overhead() { return _marking_task_overhead;} + double cleanup_sleep_factor() { return _cleanup_sleep_factor; } + double cleanup_task_overhead() { return _cleanup_task_overhead;} - HeapWord* finger() { return _finger; } - bool concurrent() { return _concurrent; } - uint active_tasks() { return _active_tasks; } - ParallelTaskTerminator* terminator() { return &_terminator; } + bool use_parallel_marking_threads() const { + assert(parallel_marking_threads() <= + max_parallel_marking_threads(), "sanity"); + assert((_parallel_workers == NULL && parallel_marking_threads() == 0) || + parallel_marking_threads() > 0, + "parallel workers not set up correctly"); + return _parallel_workers != NULL; + } + + HeapWord* finger() { return _finger; } + bool concurrent() { return _concurrent; } + uint active_tasks() { return _active_tasks; } + ParallelTaskTerminator* terminator() { return &_terminator; } // It claims the next available region to be scanned by a marking // task/thread. It might return NULL if the next region is empty or diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp index 7a102cf43d7..9782b67c007 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp @@ -131,17 +131,23 @@ void WorkerDataArray::print(int level, const char* title) { #ifndef PRODUCT +template <> const int WorkerDataArray::_uninitialized = -1; +template <> const double WorkerDataArray::_uninitialized = -1.0; +template <> const size_t WorkerDataArray::_uninitialized = (size_t)-1; + template void WorkerDataArray::reset() { for (uint i = 0; i < _length; i++) { - _data[i] = (T)-1; + _data[i] = (T)_uninitialized; } } template void WorkerDataArray::verify() { for (uint i = 0; i < _length; i++) { - assert(_data[i] >= (T)0, err_msg("Invalid data for worker %d", i)); + assert(_data[i] != _uninitialized, + err_msg("Invalid data for worker " UINT32_FORMAT ", data: %lf, uninitialized: %lf", + i, (double)_data[i], (double)_uninitialized)); } } @@ -201,20 +207,20 @@ void G1GCPhaseTimes::note_gc_end() { _last_termination_attempts.verify(); _last_gc_worker_end_times_ms.verify(); - for (uint i = 0; i < _active_gc_threads; i++) { - double worker_time = _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i); - _last_gc_worker_times_ms.set(i, worker_time); + for (uint i = 0; i < _active_gc_threads; i++) { + double worker_time = _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i); + _last_gc_worker_times_ms.set(i, worker_time); - double worker_known_time = _last_ext_root_scan_times_ms.get(i) + - _last_satb_filtering_times_ms.get(i) + - _last_update_rs_times_ms.get(i) + - _last_scan_rs_times_ms.get(i) + - _last_obj_copy_times_ms.get(i) + - _last_termination_times_ms.get(i); + double worker_known_time = _last_ext_root_scan_times_ms.get(i) + + _last_satb_filtering_times_ms.get(i) + + _last_update_rs_times_ms.get(i) + + _last_scan_rs_times_ms.get(i) + + _last_obj_copy_times_ms.get(i) + + _last_termination_times_ms.get(i); - double worker_other_time = worker_time - worker_known_time; - _last_gc_worker_other_times_ms.set(i, worker_other_time); - } + double worker_other_time = worker_time - worker_known_time; + _last_gc_worker_other_times_ms.set(i, worker_other_time); + } _last_gc_worker_times_ms.verify(); _last_gc_worker_other_times_ms.verify(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp index 99e35c63d43..b6e289ed22a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp @@ -35,6 +35,8 @@ class WorkerDataArray : public CHeapObj { const char* _print_format; bool _print_sum; + NOT_PRODUCT(static const T _uninitialized;) + // We are caching the sum and average to only have to calculate them once. // This is not done in an MT-safe way. It is intetened to allow single // threaded code to call sum() and average() multiple times in any order diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp index dde3ba4be31..6f887583cab 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp @@ -28,8 +28,9 @@ #include "memory/cardTableModRefBS.hpp" #include "memory/memRegion.hpp" #include "oops/oop.inline.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class DirtyCardQueueSet; @@ -120,6 +121,6 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS { }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 92b1cb3fc49..d362956ea80 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -287,24 +287,24 @@ "The number of times we'll force an overflow during " \ "concurrent marking") \ \ - experimental(uintx, G1NewSizePercent, 20, \ + experimental(uintx, G1NewSizePercent, 5, \ "Percentage (0-100) of the heap size to use as default " \ "minimum young gen size.") \ \ - experimental(uintx, G1MaxNewSizePercent, 80, \ + experimental(uintx, G1MaxNewSizePercent, 60, \ "Percentage (0-100) of the heap size to use as default " \ " maximum young gen size.") \ \ - experimental(uintx, G1MixedGCLiveThresholdPercent, 90, \ + experimental(uintx, G1MixedGCLiveThresholdPercent, 65, \ "Threshold for regions to be considered for inclusion in the " \ "collection set of mixed GCs. " \ "Regions with live bytes exceeding this will not be collected.") \ \ - product(uintx, G1HeapWastePercent, 5, \ + product(uintx, G1HeapWastePercent, 10, \ "Amount of space, expressed as a percentage of the heap size, " \ "that G1 is willing not to collect to avoid expensive GCs.") \ \ - product(uintx, G1MixedGCCountTarget, 4, \ + product(uintx, G1MixedGCCountTarget, 8, \ "The target number of mixed GCs after a marking cycle.") \ \ experimental(uintx, G1OldCSetRegionThresholdPercent, 10, \ diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 4f1c5493fc5..7c79195d3e5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -32,8 +32,9 @@ #include "gc_implementation/shared/spaceDecorator.hpp" #include "memory/space.inline.hpp" #include "memory/watermark.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // A HeapRegion is the smallest piece of a G1CollectedHeap that // can be collected independently. @@ -837,6 +838,6 @@ class HeapRegionClosure : public StackObj { bool complete() { return _complete; } }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp index 273322436ba..e868d870990 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @@ -878,12 +878,6 @@ void EvacuateFollowersClosureGeneral::do_void() { bool ParNewGeneration::_avoid_promotion_undo = false; -void ParNewGeneration::adjust_desired_tenuring_threshold() { - // Set the desired survivor size to half the real survivor space - _tenuring_threshold = - age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize); -} - // A Generation that does parallel young-gen collection. void ParNewGeneration::collect(bool full, @@ -1013,6 +1007,8 @@ void ParNewGeneration::collect(bool full, size_policy->reset_gc_overhead_limit_count(); assert(to()->is_empty(), "to space should be empty now"); + + adjust_desired_tenuring_threshold(); } else { assert(_promo_failure_scan_stack.is_empty(), "post condition"); _promo_failure_scan_stack.clear(true); // Clear cached segments. @@ -1035,7 +1031,6 @@ void ParNewGeneration::collect(bool full, from()->set_concurrent_iteration_safe_limit(from()->top()); to()->set_concurrent_iteration_safe_limit(to()->top()); - adjust_desired_tenuring_threshold(); if (ResizePLAB) { plab_stats()->adjust_desired_plab_sz(n_workers); } diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp index bbb6176fd08..487552bfba9 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp @@ -347,10 +347,6 @@ class ParNewGeneration: public DefNewGeneration { bool survivor_overflow() { return _survivor_overflow; } void set_survivor_overflow(bool v) { _survivor_overflow = v; } - // Adjust the tenuring threshold. See the implementation for - // the details of the policy. - virtual void adjust_desired_tenuring_threshold(); - public: ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index f68b1b5a446..078bd62aff7 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -529,7 +529,7 @@ bool PSScavenge::invoke_no_policy() { if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %u (max %u)", + gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)", size_policy->calculated_survivor_size_in_bytes(), _tenuring_threshold, MaxTenuringThreshold); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp b/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp index 50162a0adb1..311fd7771dd 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,7 @@ uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) { if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %u (max %u)", + gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)", desired_survivor_size*oopSize, result, MaxTenuringThreshold); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.cpp b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.cpp index c24fc3bbf1a..7cc37fd9453 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.cpp @@ -23,10 +23,11 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/allocationStats.hpp" #include "utilities/ostream.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Technically this should be derived from machine speed, and // ideally it would be dynamically adjusted. diff --git a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp index df1ee1ea2e5..cf7cd3ae0f2 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gcUtil.hpp" #include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" -#endif +#endif // INCLUDE_ALL_GCS class AllocationStats VALUE_OBJ_CLASS_SPEC { // A duration threshold (in ms) used to filter diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp index 77d041d70ca..6530d23b624 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "runtime/thread.hpp" -#endif +#endif // INCLUDE_ALL_GCS class VoidClosure; diff --git a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp index 4a8f85ab2a1..506322de521 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp @@ -23,11 +23,12 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gSpaceCounters.hpp" #include "memory/generation.hpp" #include "memory/resourceArea.hpp" -#endif +#endif // INCLUDE_ALL_GCS GSpaceCounters::GSpaceCounters(const char* name, int ordinal, size_t max_size, Generation* g, GenerationCounters* gc, diff --git a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp index 745dac7417b..c54e773c364 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GSPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GSPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A GSpaceCounter is a holder class for performance counters // that track a space; diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp index c1758a2fc19..5024ab9e7ab 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp @@ -25,10 +25,11 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCADAPTIVEPOLICYCOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCADAPTIVEPOLICYCOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/adaptiveSizePolicy.hpp" #include "gc_implementation/shared/gcPolicyCounters.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This class keeps statistical information and computes the // size of the heap. diff --git a/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp index f3b956ee67a..034d319b078 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A HSpaceCounter is a holder class for performance counters // that track a collections (logical spaces) in a heap; diff --git a/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.cpp index 30eb04df6a8..c844a3e596d 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.cpp @@ -23,11 +23,12 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/immutableSpace.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS void ImmutableSpace::initialize(MemRegion mr) { HeapWord* bottom = mr.start(); diff --git a/hotspot/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp b/hotspot/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp index 4d36417244c..c56cbafeb2e 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ISGCACTIVEMARK_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ISGCACTIVEMARK_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This class provides a method for block structured setting of the // _is_gc_active state without requiring accessors in CollectedHeap diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp index 3a3cbdd8c96..9752291959a 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp @@ -28,9 +28,10 @@ #include "gc_implementation/shared/markSweep.hpp" #include "gc_interface/collectedHeap.hpp" #include "utilities/stack.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" -#endif +#endif // INCLUDE_ALL_GCS inline void MarkSweep::mark_object(oop obj) { // some marks may contain information we need to preserve so we store them away diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp index 8b8f8d65e21..5621c077c38 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp @@ -25,10 +25,11 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLENUMASPACE_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLENUMASPACE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gcUtil.hpp" #include "gc_implementation/shared/mutableSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS /* * The NUMA-aware allocator (MutableNUMASpace) is basically a modification diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp index e573e02dfd6..d50edac13ca 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp @@ -23,13 +23,14 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/mutableSpace.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "oops/oop.inline.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.hpp" -#endif +#endif // INCLUDE_ALL_GCS MutableSpace::MutableSpace(size_t alignment): ImmutableSpace(), _top(NULL), _alignment(alignment) { assert(MutableSpace::alignment() >= 0 && diff --git a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp index 48dddd85b9d..f606e99e9a1 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp @@ -23,10 +23,11 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/spaceCounters.hpp" #include "memory/resourceArea.hpp" -#endif +#endif // INCLUDE_ALL_GCS SpaceCounters::SpaceCounters(const char* name, int ordinal, size_t max_size, MutableSpace* m, GenerationCounters* gc) : diff --git a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp index 6b13e5acfd2..17302d420b2 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp @@ -25,12 +25,13 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_SPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "gc_implementation/shared/immutableSpace.hpp" #include "gc_implementation/shared/mutableSpace.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A SpaceCounter is a holder class for performance counters // that track a space; diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp index ee1be4a6490..756ed28f010 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -36,9 +36,10 @@ #include "runtime/interfaceSupport.hpp" #include "utilities/dtrace.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifndef USDT2 HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool); @@ -167,7 +168,9 @@ void VM_GC_HeapInspection::doit() { ch->collect_as_vm_thread(GCCause::_heap_inspection); } } - HeapInspection::heap_inspection(_out, _need_prologue /* need_prologue */); + HeapInspection inspect(_csv_format, _print_help, _print_class_stats, + _columns); + inspect.heap_inspection(_out, _need_prologue /* need_prologue */); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp index 285ef97e378..2a416f22843 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -130,6 +130,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { outputStream* _out; bool _full_gc; bool _need_prologue; + bool _csv_format; // "comma separated values" format for spreadsheet. + bool _print_help; + bool _print_class_stats; + const char* _columns; public: VM_GC_HeapInspection(outputStream* out, bool request_full_gc, bool need_prologue) : @@ -140,6 +144,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { _out = out; _full_gc = request_full_gc; _need_prologue = need_prologue; + _csv_format = false; + _print_help = false; + _print_class_stats = false; + _columns = NULL; } ~VM_GC_HeapInspection() {} @@ -147,6 +155,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { virtual bool skip_operation() const; virtual bool doit_prologue(); virtual void doit(); + void set_csv_format(bool value) {_csv_format = value;} + void set_print_help(bool value) {_print_help = value;} + void set_print_class_stats(bool value) {_print_class_stats = value;} + void set_columns(const char* value) {_columns = value;} }; diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 0d139fdf71c..55ef63ee9d0 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -3099,9 +3099,9 @@ BytecodeInterpreter::print() { tty->print_cr("&native_fresult: " INTPTR_FORMAT, (uintptr_t) &this->_native_fresult); tty->print_cr("native_lresult: " INTPTR_FORMAT, (uintptr_t) this->_native_lresult); #endif -#if defined(IA64) && !defined(ZERO) +#if !defined(ZERO) tty->print_cr("last_Java_fp: " INTPTR_FORMAT, (uintptr_t) this->_last_Java_fp); -#endif // IA64 && !ZERO +#endif // !ZERO tty->print_cr("self_link: " INTPTR_FORMAT, (uintptr_t) this->_self_link); } diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 959388fc693..efb2a164fa2 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1241,7 +1241,7 @@ void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_kl void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { assert(EnableInvokeDynamic, ""); - pool->set_invokedynamic(); // mark header to flag active call sites + pool->set_has_invokedynamic(); // mark header to flag active call sites //resolve_pool(, method_name, method_signature, current_klass, pool, index, CHECK); Symbol* method_name = pool->name_ref_at(index); diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index 3cade72c260..e1e266ec5cf 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -145,9 +145,10 @@ enum MemoryType { mtChunk = 0x0B00, // chunk that holds content of arenas mtJavaHeap = 0x0C00, // Java heap mtClassShared = 0x0D00, // class data sharing - mt_number_of_types = 0x000D, // number of memory types (mtDontTrack + mtTest = 0x0E00, // Test type for verifying NMT + mt_number_of_types = 0x000E, // number of memory types (mtDontTrack // is not included as validate type) - mtDontTrack = 0x0E00, // memory we do not or cannot track + mtDontTrack = 0x0F00, // memory we do not or cannot track mt_masks = 0x7F00, // object type mask diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp index 725a71925dc..8ed2b61a921 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "utilities/macros.hpp" #include "gc_implementation/shared/allocationStats.hpp" #include "memory/binaryTreeDictionary.hpp" #include "memory/freeList.hpp" @@ -31,12 +32,13 @@ #include "memory/metachunk.hpp" #include "runtime/globals.hpp" #include "utilities/ostream.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp" #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS //////////////////////////////////////////////////////////////////////////////// // A binary tree based search structure for free blocks. @@ -118,7 +120,7 @@ TreeList::as_TreeList(HeapWord* addr, size_t size) { } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Specialize for AdaptiveFreeList which tries to avoid // splitting a chunk of a size that is under populated in favor of // an over populated size. The general get_better_list() just returns @@ -160,7 +162,7 @@ TreeList::get_better_list( } return curTL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> TreeList* @@ -871,9 +873,9 @@ size_t BinaryTreeDictionary::total_nodes_in_tree(TreeList class FreeList_t> void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ +void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ TreeList* nd = find_list(size); if (nd) { if (split) { @@ -900,7 +902,7 @@ void BinaryTreeDictionary::dict_census_update(size_ // This is a birth associated with a LinAB. The chunk // for the LinAB is not in the dictionary. } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { @@ -909,9 +911,9 @@ bool BinaryTreeDictionary::coal_dict_over_populated(size_t return true; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { +bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { if (FLSAlwaysCoalesceLarge) return true; TreeList* list_of_size = find_list(size); @@ -919,7 +921,7 @@ bool BinaryTreeDictionary::coal_dict_over_populated return list_of_size == NULL || list_of_size->coal_desired() <= 0 || list_of_size->count() > list_of_size->coal_desired(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Closures for walking the binary tree. // do_list() walks the free list in a node applying the closure @@ -979,7 +981,7 @@ class BeginSweepClosure : public AscendTreeCensusClosure { void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { double coalSurplusPercent = _percentage; fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); @@ -987,7 +989,7 @@ class BeginSweepClosure : public AscendTreeCensusClosure { fl->set_before_sweep(fl->count()); fl->set_bfr_surp(fl->surplus()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; // Used to search the tree until a condition is met. @@ -1134,13 +1136,13 @@ class setTreeSurplusClosure : public AscendTreeCensusClosure* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { double splitSurplusPercent = percentage; fl->set_surplus(fl->count() - (ssize_t)((double)fl->desired() * splitSurplusPercent)); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1157,7 +1159,7 @@ class setTreeHintsClosure : public DescendTreeCensusClosure setTreeHintsClosure(size_t v) { hint = v; } void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { fl->set_hint(hint); assert(fl->hint() == 0 || fl->hint() > fl->size(), @@ -1166,7 +1168,7 @@ class setTreeHintsClosure : public DescendTreeCensusClosure hint = fl->size(); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1180,7 +1182,7 @@ template class FreeList_t> class clearTreeCensusClosure : public AscendTreeCensusClosure { void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { fl->set_prev_sweep(fl->count()); fl->set_coal_births(0); @@ -1188,7 +1190,7 @@ class clearTreeCensusClosure : public AscendTreeCensusClosureset_split_births(0); fl->set_split_deaths(0); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1252,7 +1254,7 @@ class PrintTreeCensusClosure : public AscendTreeCensusClosureset_count( total()->count() + fl->count() ); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { if (++_print_line >= 40) { FreeList_t::print_labels_on(gclog_or_tty, "size"); @@ -1271,7 +1273,7 @@ class PrintTreeCensusClosure : public AscendTreeCensusClosureset_split_births(total()->split_births() + fl->split_births()); total()->set_split_deaths(total()->split_deaths() + fl->split_deaths()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1286,9 +1288,9 @@ void BinaryTreeDictionary::print_dict_census(void) const { FreeList_t::print_labels_on(gclog_or_tty, " "); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -void BinaryTreeDictionary::print_dict_census(void) const { +void AFLBinaryTreeDictionary::print_dict_census(void) const { gclog_or_tty->print("\nBinaryTree\n"); AdaptiveFreeList::print_labels_on(gclog_or_tty, "size"); @@ -1308,7 +1310,7 @@ void BinaryTreeDictionary::print_dict_census(void) (double)(total->desired() - total->count()) /(total->desired() != 0 ? (double)total->desired() : 1.0)); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> class PrintFreeListsClosure : public AscendTreeCensusClosure { @@ -1414,10 +1416,10 @@ template class BinaryTreeDictionary; template class TreeChunk; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Explicitly instantiate these types for FreeChunk. template class TreeList; template class BinaryTreeDictionary; template class TreeChunk; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp index 757eb4fdac9..460a4ea29e1 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp @@ -43,6 +43,10 @@ template class FreeList_t> class AscendTreeCens template class FreeList_t> class DescendTreeCensusClosure; template class FreeList_t> class DescendTreeSearchClosure; +class FreeChunk; +template class AdaptiveFreeList; +typedef BinaryTreeDictionary AFLBinaryTreeDictionary; + template class FreeList_t> class TreeList : public FreeList_t { friend class TreeChunk; diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp index bd0c79ed439..d3fa82d8566 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp @@ -34,6 +34,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/virtualspace.hpp" #include "services/memTracker.hpp" +#include "utilities/macros.hpp" #ifdef COMPILER1 #include "c1/c1_LIR.hpp" #include "c1/c1_LIRGenerator.hpp" @@ -499,13 +500,13 @@ void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp, int n_threads = SharedHeap::heap()->n_par_threads(); bool is_par = n_threads > 0; if (is_par) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS assert(SharedHeap::heap()->n_par_threads() == SharedHeap::heap()->workers()->active_workers(), "Mismatch"); non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads); -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("Parallel gc not supported here."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { // We do not call the non_clean_card_iterate_serial() version below because // we want to clear the cards (which non_clean_card_iterate_serial() does not diff --git a/hotspot/src/share/vm/memory/cardTableRS.cpp b/hotspot/src/share/vm/memory/cardTableRS.cpp index d16b3ec0be5..d92de481644 100644 --- a/hotspot/src/share/vm/memory/cardTableRS.cpp +++ b/hotspot/src/share/vm/memory/cardTableRS.cpp @@ -31,10 +31,11 @@ #include "oops/oop.inline.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS CardTableRS::CardTableRS(MemRegion whole_heap, int max_covered_regions) : @@ -42,7 +43,7 @@ CardTableRS::CardTableRS(MemRegion whole_heap, _cur_youngergen_card_val(youngergenP1_card), _regions_to_iterate(max_covered_regions - 1) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { _ct_bs = new G1SATBCardTableLoggingModRefBS(whole_heap, max_covered_regions); diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp index b13d9761120..2645cec46ae 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -39,10 +39,11 @@ #include "runtime/java.hpp" #include "runtime/thread.inline.hpp" #include "runtime/vmThread.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsGCAdaptivePolicyCounters.hpp" -#endif +#endif // INCLUDE_ALL_GCS // CollectorPolicy methods. @@ -235,6 +236,18 @@ void TwoGenerationCollectorPolicy::initialize_flags() { if (NewSize + OldSize > MaxHeapSize) { MaxHeapSize = NewSize + OldSize; } + + if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) { + // NewRatio will be used later to set the young generation size so we use + // it to calculate how big the heap should be based on the requested OldSize + // and NewRatio. + assert(NewRatio > 0, "NewRatio should have been set up earlier"); + size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1); + + calculated_heapsize = align_size_up(calculated_heapsize, max_alignment()); + MaxHeapSize = calculated_heapsize; + InitialHeapSize = calculated_heapsize; + } MaxHeapSize = align_size_up(MaxHeapSize, max_alignment()); always_do_update_barrier = UseConcMarkSweepGC; @@ -384,14 +397,15 @@ void GenCollectorPolicy::initialize_size_info() { // keeping it simple also seems a worthwhile goal. bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - size_t heap_size, - size_t min_gen0_size) { + const size_t heap_size, + const size_t min_gen1_size) { bool result = false; + if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) { - if (((*gen0_size_ptr + OldSize) > heap_size) && - (heap_size - min_gen0_size) >= min_alignment()) { - // Adjust gen0 down to accomodate OldSize - *gen0_size_ptr = heap_size - min_gen0_size; + if ((heap_size < (*gen0_size_ptr + min_gen1_size)) && + (heap_size >= min_gen1_size + min_alignment())) { + // Adjust gen0 down to accommodate min_gen1_size + *gen0_size_ptr = heap_size - min_gen1_size; *gen0_size_ptr = MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()), min_alignment()); diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp index a079f71b95b..4acf7ba780c 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -29,6 +29,7 @@ #include "memory/barrierSet.hpp" #include "memory/generationSpec.hpp" #include "memory/genRemSet.hpp" +#include "utilities/macros.hpp" // This class (or more correctly, subtypes of this class) // are used to define global garbage collector attributes. @@ -48,10 +49,10 @@ class GenCollectorPolicy; class TwoGenerationCollectorPolicy; class AdaptiveSizePolicy; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class ConcurrentMarkSweepPolicy; class G1CollectorPolicy; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS class GCPolicyCounters; class MarkSweepPolicy; @@ -134,21 +135,21 @@ class CollectorPolicy : public CHeapObj { virtual GenCollectorPolicy* as_generation_policy() { return NULL; } virtual TwoGenerationCollectorPolicy* as_two_generation_policy() { return NULL; } virtual MarkSweepPolicy* as_mark_sweep_policy() { return NULL; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS virtual ConcurrentMarkSweepPolicy* as_concurrent_mark_sweep_policy() { return NULL; } virtual G1CollectorPolicy* as_g1_policy() { return NULL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Note that these are not virtual. bool is_generation_policy() { return as_generation_policy() != NULL; } bool is_two_generation_policy() { return as_two_generation_policy() != NULL; } bool is_mark_sweep_policy() { return as_mark_sweep_policy() != NULL; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS bool is_concurrent_mark_sweep_policy() { return as_concurrent_mark_sweep_policy() != NULL; } bool is_g1_policy() { return as_g1_policy() != NULL; } -#else // SERIALGC +#else // INCLUDE_ALL_GCS bool is_concurrent_mark_sweep_policy() { return false; } bool is_g1_policy() { return false; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS virtual BarrierSet::Name barrier_set_name() = 0; @@ -321,7 +322,7 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy { // Returns true is gen0 sizes were adjusted bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - size_t heap_size, size_t min_gen1_size); + const size_t heap_size, const size_t min_gen1_size); }; class MarkSweepPolicy : public TwoGenerationCollectorPolicy { diff --git a/hotspot/src/share/vm/memory/defNewGeneration.cpp b/hotspot/src/share/vm/memory/defNewGeneration.cpp index cca7cd0e704..689ce7b8bbf 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp @@ -550,6 +550,11 @@ HeapWord* DefNewGeneration::expand_and_allocate(size_t size, return allocate(size, is_tlab); } +void DefNewGeneration::adjust_desired_tenuring_threshold() { + // Set the desired survivor size to half the real survivor space + _tenuring_threshold = + age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize); +} void DefNewGeneration::collect(bool full, bool clear_all_soft_refs, @@ -649,9 +654,7 @@ void DefNewGeneration::collect(bool full, assert(to()->is_empty(), "to space should be empty now"); - // Set the desired survivor size to half the real survivor space - _tenuring_threshold = - age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize); + adjust_desired_tenuring_threshold(); // A successful scavenge should restart the GC time limit count which is // for full GC's. diff --git a/hotspot/src/share/vm/memory/defNewGeneration.hpp b/hotspot/src/share/vm/memory/defNewGeneration.hpp index b7c794d86c2..38ea742b38a 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.hpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp @@ -124,7 +124,9 @@ protected: _should_allocate_from_space = true; } - protected: + // Tenuring + void adjust_desired_tenuring_threshold(); + // Spaces EdenSpace* _eden_space; ContiguousSpace* _from_space; diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index fe0958073e3..fec0957f145 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -210,13 +210,14 @@ void FileMapInfo::open_for_write() { tty->print_cr(" %s", _full_path); } - // Remove the existing file in case another process has it open. - remove(_full_path); -#ifdef _WINDOWS // if 0444 is used on Windows, then remove() will fail. - int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0744); -#else - int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); +#ifdef _WINDOWS // On Windows, need WRITE permission to remove the file. + chmod(_full_path, _S_IREAD | _S_IWRITE); #endif + + // Use remove() to delete the existing file because, on Unix, this will + // allow processes that have it open continued access to the file. + remove(_full_path); + int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); if (fd < 0) { fail_stop("Unable to create shared archive file %s.", _full_path); } diff --git a/hotspot/src/share/vm/memory/freeBlockDictionary.cpp b/hotspot/src/share/vm/memory/freeBlockDictionary.cpp index 918a80f1fb3..713036ea500 100644 --- a/hotspot/src/share/vm/memory/freeBlockDictionary.cpp +++ b/hotspot/src/share/vm/memory/freeBlockDictionary.cpp @@ -23,13 +23,15 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/freeBlockDictionary.hpp" #include "memory/metablock.hpp" #include "memory/metachunk.hpp" #include "runtime/thread.inline.hpp" +#include "utilities/macros.hpp" #ifndef PRODUCT template Mutex* FreeBlockDictionary::par_lock() const { @@ -56,7 +58,7 @@ template void FreeBlockDictionary::verify_par_locked() cons template class FreeBlockDictionary; template class FreeBlockDictionary; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Explicitly instantiate for FreeChunk template class FreeBlockDictionary; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/memory/freeList.cpp b/hotspot/src/share/vm/memory/freeList.cpp index f5cd80545c0..05e4ef0a290 100644 --- a/hotspot/src/share/vm/memory/freeList.cpp +++ b/hotspot/src/share/vm/memory/freeList.cpp @@ -31,10 +31,11 @@ #include "runtime/globals.hpp" #include "runtime/mutex.hpp" #include "runtime/vmThread.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Free list. A FreeList is used to access a linked list of chunks // of space in the heap. The head and tail are maintained so that @@ -341,6 +342,6 @@ void FreeList::print_on(outputStream* st, const char* c) const { template class FreeList; template class FreeList; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template class FreeList; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 13778b06d50..9d65cc15701 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -51,10 +51,11 @@ #include "services/memoryService.hpp" #include "utilities/vmError.hpp" #include "utilities/workgroup.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp" -#endif +#endif // INCLUDE_ALL_GCS GenCollectedHeap* GenCollectedHeap::_gch; NOT_PRODUCT(size_t GenCollectedHeap::_skip_header_HeapWords = 0;) @@ -141,14 +142,14 @@ jint GenCollectedHeap::initialize() { } clear_incremental_collection_failed(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If we are running CMS, create the collector responsible // for collecting the CMS generations. if (collector_policy()->is_concurrent_mark_sweep_policy()) { bool success = create_cms_collector(); if (!success) return JNI_ENOMEM; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return JNI_OK; } @@ -686,12 +687,12 @@ size_t GenCollectedHeap::unsafe_max_alloc() { void GenCollectedHeap::collect(GCCause::Cause cause) { if (should_do_concurrent_full_gc(cause)) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // mostly concurrent full collection collect_mostly_concurrent(cause); -#else // SERIALGC +#else // INCLUDE_ALL_GCS ShouldNotReachHere(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { #ifdef ASSERT if (cause == GCCause::_scavenge_alot) { @@ -736,7 +737,7 @@ void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS bool GenCollectedHeap::create_cms_collector() { assert(((_gens[1]->kind() == Generation::ConcurrentMarkSweep) || @@ -772,7 +773,7 @@ void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) { VMThread::execute(&op); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) { do_full_collection(clear_all_soft_refs, _n_gens - 1); @@ -1116,22 +1117,22 @@ void GenCollectedHeap::gc_threads_do(ThreadClosure* tc) const { if (workers() != NULL) { workers()->threads_do(tc); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::threads_do(tc); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } void GenCollectedHeap::print_gc_threads_on(outputStream* st) const { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseParNewGC) { workers()->print_worker_threads_on(st); } if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::print_all_on(st); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } void GenCollectedHeap::print_tracing_info() const { diff --git a/hotspot/src/share/vm/memory/generationSpec.cpp b/hotspot/src/share/vm/memory/generationSpec.cpp index 30c79ea6f29..d97a56fbbcc 100644 --- a/hotspot/src/share/vm/memory/generationSpec.cpp +++ b/hotspot/src/share/vm/memory/generationSpec.cpp @@ -30,11 +30,12 @@ #include "memory/generationSpec.hpp" #include "memory/tenuredGeneration.hpp" #include "runtime/java.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/asParNewGeneration.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/parNew/parNewGeneration.hpp" -#endif +#endif // INCLUDE_ALL_GCS Generation* GenerationSpec::init(ReservedSpace rs, int level, GenRemSet* remset) { @@ -45,7 +46,7 @@ Generation* GenerationSpec::init(ReservedSpace rs, int level, case Generation::MarkSweepCompact: return new TenuredGeneration(rs, init_size(), level, remset); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: return new ParNewGeneration(rs, init_size(), level); @@ -94,7 +95,7 @@ Generation* GenerationSpec::init(ReservedSpace rs, int level, return g; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: guarantee(false, "unrecognized GenerationName"); diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index 71674fcb2d5..a51ea1d1561 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -23,15 +23,17 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "gc_interface/collectedHeap.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/heapInspection.hpp" #include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // HeapInspection @@ -41,12 +43,24 @@ int KlassInfoEntry::compare(KlassInfoEntry* e1, KlassInfoEntry* e2) { } else if(e1->_instance_words < e2->_instance_words) { return 1; } - return 0; + // Sort alphabetically, note 'Z' < '[' < 'a', but it's better to group + // the array classes before all the instance classes. + ResourceMark rm; + const char* name1 = e1->klass()->external_name(); + const char* name2 = e2->klass()->external_name(); + bool d1 = (name1[0] == '['); + bool d2 = (name2[0] == '['); + if (d1 && !d2) { + return -1; + } else if (d2 && !d1) { + return 1; + } else { + return strcmp(name1, name2); + } } -void KlassInfoEntry::print_on(outputStream* st) const { - ResourceMark rm; - const char* name;; +const char* KlassInfoEntry::name() const { + const char* name; if (_klass->name() != NULL) { name = _klass->external_name(); } else { @@ -60,11 +74,17 @@ void KlassInfoEntry::print_on(outputStream* st) const { if (_klass == Universe::longArrayKlassObj()) name = ""; else name = ""; } + return name; +} + +void KlassInfoEntry::print_on(outputStream* st) const { + ResourceMark rm; + // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit st->print_cr(INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13) " %s", (jlong) _instance_count, (julong) _instance_words * HeapWordSize, - name); + name()); } KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) { @@ -101,7 +121,14 @@ void KlassInfoBucket::empty() { } } -KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { +void KlassInfoTable::AllClassesFinder::do_klass(Klass* k) { + // This has the SIDE EFFECT of creating a KlassInfoEntry + // for , if one doesn't exist yet. + _table->lookup(k); +} + +KlassInfoTable::KlassInfoTable(int size, HeapWord* ref, + bool need_class_stats) { _size = 0; _ref = ref; _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal); @@ -110,6 +137,10 @@ KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } + if (need_class_stats) { + AllClassesFinder finder(this); + ClassLoaderDataGraph::classes_do(&finder); + } } } @@ -165,7 +196,8 @@ int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) { return (*e1)->compare(*e1,*e2); } -KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) : +KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) : + _cit(cit), _title(title) { _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(estimatedCount,true); } @@ -196,9 +228,205 @@ void KlassInfoHisto::print_elements(outputStream* st) const { total, totalw * HeapWordSize); } -void KlassInfoHisto::print_on(outputStream* st) const { - st->print_cr("%s",title()); - print_elements(st); +#define MAKE_COL_NAME(field, name, help) #name, +#define MAKE_COL_HELP(field, name, help) help, + +static const char *name_table[] = { + HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_NAME) +}; + +static const char *help_table[] = { + HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_HELP) +}; + +bool KlassInfoHisto::is_selected(const char *col_name) { + if (_selected_columns == NULL) { + return true; + } + if (strcmp(_selected_columns, col_name) == 0) { + return true; + } + + const char *start = strstr(_selected_columns, col_name); + if (start == NULL) { + return false; + } + + // The following must be true, because _selected_columns != col_name + if (start > _selected_columns && start[-1] != ',') { + return false; + } + char x = start[strlen(col_name)]; + if (x != ',' && x != '\0') { + return false; + } + + return true; +} + +void KlassInfoHisto::print_title(outputStream* st, bool csv_format, + bool selected[], int width_table[], + const char *name_table[]) { + if (csv_format) { + st->print("Index,Super"); + for (int c=0; cprint(",%s", name_table[c]);} + } + st->print(",ClassName"); + } else { + st->print("Index Super"); + for (int c=0; cprint(str_fmt(width_table[c]), name_table[c]);} + } + st->print(" ClassName"); + } + + if (is_selected("ClassLoader")) { + st->print(",ClassLoader"); + } + st->cr(); +} + +void KlassInfoHisto::print_class_stats(outputStream* st, + bool csv_format, const char *columns) { + ResourceMark rm; + KlassSizeStats sz, sz_sum; + int i; + julong *col_table = (julong*)(&sz); + julong *colsum_table = (julong*)(&sz_sum); + int width_table[KlassSizeStats::_num_columns]; + bool selected[KlassSizeStats::_num_columns]; + + _selected_columns = columns; + + memset(&sz_sum, 0, sizeof(sz_sum)); + for (int c=0; clength(); i++) { + elements()->at(i)->set_index(i+1); + } + + for (int pass=1; pass<=2; pass++) { + if (pass == 2) { + print_title(st, csv_format, selected, width_table, name_table); + } + for(i=0; i < elements()->length(); i++) { + KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); + const Klass* k = e->klass(); + + memset(&sz, 0, sizeof(sz)); + sz._inst_count = e->count(); + sz._inst_bytes = HeapWordSize * e->words(); + k->collect_statistics(&sz); + sz._total_bytes = sz._ro_bytes + sz._rw_bytes; + + if (pass == 1) { + for (int c=0; coop_is_instance()) { + Klass* super = ((InstanceKlass*)k)->java_super(); + if (super) { + KlassInfoEntry* super_e = _cit->lookup(super); + if (super_e) { + super_index = super_e->index(); + } + } + } + + if (csv_format) { + st->print("%d,%d", e->index(), super_index); + for (int c=0; cprint("," JULONG_FORMAT, col_table[c]);} + } + st->print(",%s",e->name()); + } else { + st->print("%5d %5d", e->index(), super_index); + for (int c=0; cprint(" %s", e->name()); + } + if (is_selected("ClassLoader")) { + ClassLoaderData* loader_data = k->class_loader_data(); + st->print(","); + loader_data->print_value_on(st); + } + st->cr(); + } + } + + if (pass == 1) { + for (int c=0; cprint(","); + for (int c=0; cprint("," JULONG_FORMAT, colsum_table[c]);} + } + } else { + st->print(" "); + for (int c=0; cprint(" Total"); + if (sz_sum._total_bytes > 0) { + st->cr(); + st->print(" "); + for (int c=0; cprint(str_fmt(width_table[c]), "-"); + break; + default: + { + double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; + st->print(perc_fmt(width_table[c]), perc); + } + } + } + } + } + } + st->cr(); + + if (!csv_format) { + print_title(st, csv_format, selected, width_table, name_table); + } +} + +julong KlassInfoHisto::annotations_bytes(Array* p) const { + julong bytes = 0; + if (p != NULL) { + for (int i = 0; i < p->length(); i++) { + bytes += count_bytes_array(p->at(i)); + } + bytes += count_bytes_array(p); + } + return bytes; +} + +void KlassInfoHisto::print_histo_on(outputStream* st, bool print_stats, + bool csv_format, const char *columns) { + if (print_stats) { + print_class_stats(st, csv_format, columns); + } else { + st->print_cr("%s",title()); + print_elements(st); + } } class HistoClosure : public KlassInfoClosure { @@ -236,8 +464,26 @@ void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { CollectedHeap* heap = Universe::heap(); bool is_shared_heap = false; + if (_print_help) { + for (int c=0; cprint("%s:\n\t", name_table[c]); + const int max_col = 60; + int col = 0; + for (const char *p = help_table[c]; *p; p++,col++) { + if (col >= max_col && *p == ' ') { + st->print("\n\t"); + col = 0; + } else { + st->print("%c", *p); + } + } + st->print_cr(".\n"); + } + return; + } + // Collect klass instance info - KlassInfoTable cit(KlassInfoTable::cit_size, ref); + KlassInfoTable cit(KlassInfoTable::cit_size, ref, _print_class_stats); if (!cit.allocation_failed()) { // Iterate over objects in the heap RecordInstanceClosure ric(&cit); @@ -252,14 +498,14 @@ void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { missed_count); } // Sort and print klass instance info - KlassInfoHisto histo("\n" - " num #instances #bytes class name\n" - "----------------------------------------------", - KlassInfoHisto::histo_initial_size); + const char *title = "\n" + " num #instances #bytes class name\n" + "----------------------------------------------"; + KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size); HistoClosure hc(&histo); cit.iterate(&hc); histo.sort(); - histo.print_on(st); + histo.print_histo_on(st, _print_class_stats, _csv_format, _columns); } else { st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); } diff --git a/hotspot/src/share/vm/memory/heapInspection.hpp b/hotspot/src/share/vm/memory/heapInspection.hpp index 72e675850d4..c080cb8425b 100644 --- a/hotspot/src/share/vm/memory/heapInspection.hpp +++ b/hotspot/src/share/vm/memory/heapInspection.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -27,6 +27,8 @@ #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/annotations.hpp" +#include "utilities/macros.hpp" #if INCLUDE_SERVICES @@ -44,16 +46,144 @@ // to KlassInfoEntry's and is used to sort // the entries. +#define HEAP_INSPECTION_COLUMNS_DO(f) \ + f(inst_size, InstSize, \ + "Size of each object instance of the Java class") \ + f(inst_count, InstCount, \ + "Number of object instances of the Java class") \ + f(inst_bytes, InstBytes, \ + "This is usually (InstSize * InstNum). The only exception is " \ + "java.lang.Class, whose InstBytes also includes the slots " \ + "used to store static fields. InstBytes is not counted in " \ + "ROAll, RWAll or Total") \ + f(mirror_bytes, Mirror, \ + "Size of the Klass::java_mirror() object") \ + f(klass_bytes, KlassBytes, \ + "Size of the InstanceKlass or ArrayKlass for this class. " \ + "Note that this includes VTab, ITab, OopMap") \ + f(secondary_supers_bytes, K_secondary_supers, \ + "Number of bytes used by the Klass::secondary_supers() array") \ + f(vtab_bytes, VTab, \ + "Size of the embedded vtable in InstanceKlass") \ + f(itab_bytes, ITab, \ + "Size of the embedded itable in InstanceKlass") \ + f(nonstatic_oopmap_bytes, OopMap, \ + "Size of the embedded nonstatic_oop_map in InstanceKlass") \ + f(methods_array_bytes, IK_methods, \ + "Number of bytes used by the InstanceKlass::methods() array") \ + f(method_ordering_bytes, IK_method_ordering, \ + "Number of bytes used by the InstanceKlass::method_ordering() array") \ + f(local_interfaces_bytes, IK_local_interfaces, \ + "Number of bytes used by the InstanceKlass::local_interfaces() array") \ + f(transitive_interfaces_bytes, IK_transitive_interfaces, \ + "Number of bytes used by the InstanceKlass::transitive_interfaces() array") \ + f(fields_bytes, IK_fields, \ + "Number of bytes used by the InstanceKlass::fields() array") \ + f(inner_classes_bytes, IK_inner_classes, \ + "Number of bytes used by the InstanceKlass::inner_classes() array") \ + f(signers_bytes, IK_signers, \ + "Number of bytes used by the InstanceKlass::singers() array") \ + f(class_annotations_bytes, class_annotations, \ + "Size of class annotations") \ + f(fields_annotations_bytes, fields_annotations, \ + "Size of field annotations") \ + f(methods_annotations_bytes, methods_annotations, \ + "Size of method annotations") \ + f(methods_parameter_annotations_bytes, methods_parameter_annotations, \ + "Size of method parameter annotations") \ + f(methods_default_annotations_bytes, methods_default_annotations, \ + "Size of methods default annotations") \ + f(type_annotations_bytes, type_annotations, \ + "Size of type annotations") \ + f(annotations_bytes, annotations, \ + "Size of all annotations") \ + f(cp_bytes, Cp, \ + "Size of InstanceKlass::constants()") \ + f(cp_tags_bytes, CpTags, \ + "Size of InstanceKlass::constants()->tags()") \ + f(cp_cache_bytes, CpCache, \ + "Size of InstanceKlass::constants()->cache()") \ + f(cp_operands_bytes, CpOperands, \ + "Size of InstanceKlass::constants()->operands()") \ + f(cp_refmap_bytes, CpRefMap, \ + "Size of InstanceKlass::constants()->reference_map()") \ + f(cp_all_bytes, CpAll, \ + "Sum of Cp + CpTags + CpCache + CpOperands + CpRefMap") \ + f(method_count, MethodCount, \ + "Number of methods in this class") \ + f(method_bytes, MethodBytes, \ + "Size of the Method object") \ + f(const_method_bytes, ConstMethod, \ + "Size of the ConstMethod object") \ + f(method_data_bytes, MethodData, \ + "Size of the MethodData object") \ + f(stackmap_bytes, StackMap, \ + "Size of the stackmap_data") \ + f(bytecode_bytes, Bytecodes, \ + "Of the MethodBytes column, how much are the space taken up by bytecodes") \ + f(method_all_bytes, MethodAll, \ + "Sum of MethodBytes + Constmethod + Stackmap + Methoddata") \ + f(ro_bytes, ROAll, \ + "Size of all class meta data that could (potentially) be placed " \ + "in read-only memory. (This could change with CDS design)") \ + f(rw_bytes, RWAll, \ + "Size of all class meta data that must be placed in read/write " \ + "memory. (This could change with CDS design) ") \ + f(total_bytes, Total, \ + "ROAll + RWAll. Note that this does NOT include InstBytes.") + +// Size statistics for a Klass - filled in by Klass::collect_statistics() +class KlassSizeStats { +public: +#define COUNT_KLASS_SIZE_STATS_FIELD(field, name, help) _index_ ## field, +#define DECLARE_KLASS_SIZE_STATS_FIELD(field, name, help) julong _ ## field; + + enum { + HEAP_INSPECTION_COLUMNS_DO(COUNT_KLASS_SIZE_STATS_FIELD) + _num_columns + }; + + HEAP_INSPECTION_COLUMNS_DO(DECLARE_KLASS_SIZE_STATS_FIELD) + + static int count(oop x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + static int count_array(objArrayOop x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count_array(T* x) { + if (x == NULL) { + return 0; + } + if (x->length() == 0) { + // This is a shared array, e.g., Universe::the_empty_int_array(). Don't + // count it to avoid double-counting. + return 0; + } + return HeapWordSize * x->size(); + } +}; + + + + class KlassInfoEntry: public CHeapObj { private: KlassInfoEntry* _next; Klass* _klass; long _instance_count; size_t _instance_words; + long _index; public: KlassInfoEntry(Klass* k, KlassInfoEntry* next) : - _klass(k), _instance_count(0), _instance_words(0), _next(next) + _klass(k), _instance_count(0), _instance_words(0), _next(next), _index(-1) {} KlassInfoEntry* next() { return _next; } bool is_equal(Klass* k) { return k == _klass; } @@ -62,8 +192,11 @@ class KlassInfoEntry: public CHeapObj { void set_count(long ct) { _instance_count = ct; } size_t words() { return _instance_words; } void set_words(size_t wds) { _instance_words = wds; } + void set_index(long index) { _index = index; } + long index() { return _index; } int compare(KlassInfoEntry* e1, KlassInfoEntry* e2); void print_on(outputStream* st) const; + const char* name() const; }; class KlassInfoClosure: public StackObj { @@ -95,45 +228,132 @@ class KlassInfoTable: public StackObj { KlassInfoBucket* _buckets; uint hash(Klass* p); - KlassInfoEntry* lookup(Klass* const k); + KlassInfoEntry* lookup(Klass* const k); // allocates if not found! + + class AllClassesFinder : public KlassClosure { + KlassInfoTable *_table; + public: + AllClassesFinder(KlassInfoTable* table) : _table(table) {} + virtual void do_klass(Klass* k); + }; public: // Table size enum { cit_size = 20011 }; - KlassInfoTable(int size, HeapWord* ref); + KlassInfoTable(int size, HeapWord* ref, bool need_class_stats); ~KlassInfoTable(); bool record_instance(const oop obj); void iterate(KlassInfoClosure* cic); bool allocation_failed() { return _buckets == NULL; } + + friend class KlassInfoHisto; }; class KlassInfoHisto : public StackObj { private: + KlassInfoTable *_cit; GrowableArray* _elements; GrowableArray* elements() const { return _elements; } const char* _title; const char* title() const { return _title; } static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); void print_elements(outputStream* st) const; + void print_class_stats(outputStream* st, bool csv_format, const char *columns); + julong annotations_bytes(Array* p) const; + const char *_selected_columns; + bool is_selected(const char *col_name); + void print_title(outputStream* st, bool csv_format, + bool selected_columns_table[], int width_table[], + const char *name_table[]); + + template static int count_bytes(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count_bytes_array(T* x) { + if (x == NULL) { + return 0; + } + if (x->length() == 0) { + // This is a shared array, e.g., Universe::the_empty_int_array(). Don't + // count it to avoid double-counting. + return 0; + } + return HeapWordSize * x->size(); + } + + // returns a format string to print a julong with the given width. E.g, + // printf(num_fmt(6), julong(10)) would print out the number 10 with 4 + // leading spaces. + static void print_julong(outputStream* st, int width, julong n) { + int num_spaces = width - julong_width(n); + if (num_spaces > 0) { + st->print(str_fmt(num_spaces), ""); + } + st->print(JULONG_FORMAT, n); + } + + static char* perc_fmt(int width) { + static char buf[32]; + jio_snprintf(buf, sizeof(buf), "%%%d.1f%%%%", width-1); + return buf; + } + + static char* str_fmt(int width) { + static char buf[32]; + jio_snprintf(buf, sizeof(buf), "%%%ds", width); + return buf; + } + + static int julong_width(julong n) { + if (n == 0) { + return 1; + } + int w = 0; + while (n > 0) { + n /= 10; + w += 1; + } + return w; + } + + static int col_width(julong n, const char *name) { + int w = julong_width(n); + int min = (int)(strlen(name)); + if (w < min) { + w = min; + } + // add a leading space for separation. + return w + 1; + } + public: enum { histo_initial_size = 1000 }; - KlassInfoHisto(const char* title, + KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount); ~KlassInfoHisto(); void add(KlassInfoEntry* cie); - void print_on(outputStream* st) const; + void print_histo_on(outputStream* st, bool print_class_stats, bool csv_format, const char *columns); void sort(); }; #endif // INCLUDE_SERVICES -class HeapInspection : public AllStatic { +class HeapInspection : public StackObj { + bool _csv_format; // "comma separated values" format for spreadsheet. + bool _print_help; + bool _print_class_stats; + const char* _columns; public: - static void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; + HeapInspection(bool csv_format, bool print_help, + bool print_class_stats, const char *columns) : + _csv_format(csv_format), _print_help(print_help), + _print_class_stats(print_class_stats), _columns(columns) {} + void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; static void find_instances_at_safepoint(Klass* k, GrowableArray* result) NOT_SERVICES_RETURN; }; diff --git a/hotspot/src/share/vm/memory/metadataFactory.hpp b/hotspot/src/share/vm/memory/metadataFactory.hpp index 3c4689c479a..fce8d9b34d7 100644 --- a/hotspot/src/share/vm/memory/metadataFactory.hpp +++ b/hotspot/src/share/vm/memory/metadataFactory.hpp @@ -66,7 +66,11 @@ class MetadataFactory : AllStatic { if (data != NULL) { assert(loader_data != NULL, "shouldn't pass null"); int size = data->size(); - loader_data->metaspace_non_null()->deallocate((MetaWord*)data, size, false); + if (DumpSharedSpaces) { + loader_data->ro_metaspace()->deallocate((MetaWord*)data, size, false); + } else { + loader_data->metaspace_non_null()->deallocate((MetaWord*)data, size, false); + } } } @@ -77,6 +81,7 @@ class MetadataFactory : AllStatic { assert(loader_data != NULL, "shouldn't pass null"); int size = md->size(); // Call metadata's deallocate function which will call deallocate fields + assert(!DumpSharedSpaces, "cannot deallocate metadata when dumping CDS archive"); assert(!md->on_stack(), "can't deallocate things on stack"); md->deallocate_contents(loader_data); loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, md->is_klass()); diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index f54803a190f..c629e175f09 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -1737,10 +1737,10 @@ void SpaceManager::get_initial_chunk_sizes(Metaspace::MetaspaceType type, *class_chunk_word_size = ClassSmallChunk; break; } - assert(chunk_word_size != 0 && class_chunk_word_size != 0, + assert(*chunk_word_size != 0 && *class_chunk_word_size != 0, err_msg("Initial chunks sizes bad: data " SIZE_FORMAT " class " SIZE_FORMAT, - chunk_word_size, class_chunk_word_size)); + *chunk_word_size, *class_chunk_word_size)); } size_t SpaceManager::sum_free_in_chunks_in_use() const { @@ -2040,7 +2040,7 @@ SpaceManager::~SpaceManager() { align_size_up(humongous_chunks->word_size(), HumongousChunkGranularity), err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT - " granularity " SIZE_FORMAT, + " granularity %d", humongous_chunks->word_size(), HumongousChunkGranularity)); Metachunk* next_humongous_chunks = humongous_chunks->next(); chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); @@ -2264,7 +2264,8 @@ void SpaceManager::verify_allocation_total() { } MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); assert(allocation_total() == sum_used_in_chunks_in_use(), - err_msg("allocation total is not consistent %d vs %d", + err_msg("allocation total is not consistent " SIZE_FORMAT + " vs " SIZE_FORMAT, allocation_total(), sum_used_in_chunks_in_use())); } @@ -2578,7 +2579,8 @@ void Metaspace::global_initialize() { // argument passed in is at the top of the compressed space void Metaspace::initialize_class_space(ReservedSpace rs) { // The reserved space size may be bigger because of alignment, esp with UseLargePages - assert(rs.size() >= ClassMetaspaceSize, err_msg("%d != %d", rs.size(), ClassMetaspaceSize)); + assert(rs.size() >= ClassMetaspaceSize, + err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize)); _class_space_list = new VirtualSpaceList(rs); } diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 5954e43d05a..4f53114c6cd 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -373,17 +373,44 @@ void VM_PopulateDumpSharedSpace::doit() { md_top = wc.get_top(); // Print shared spaces all the time - const char* fmt = "%s space: " PTR_FORMAT " out of " PTR_FORMAT " words allocated at " PTR_FORMAT "."; + const char* fmt = "%s space: %9d [ %4.1f%% of total] out of %9d bytes [%4.1f%% used] at " PTR_FORMAT; Metaspace* ro_space = _loader_data->ro_metaspace(); Metaspace* rw_space = _loader_data->rw_metaspace(); - tty->print_cr(fmt, "ro", ro_space->used_words(Metaspace::NonClassType), - ro_space->capacity_words(Metaspace::NonClassType), - ro_space->bottom()); - tty->print_cr(fmt, "rw", rw_space->used_words(Metaspace::NonClassType), - rw_space->capacity_words(Metaspace::NonClassType), - rw_space->bottom()); - tty->print_cr(fmt, "md", md_top - md_low, md_end-md_low, md_low); - tty->print_cr(fmt, "mc", mc_top - mc_low, mc_end-mc_low, mc_low); + const size_t BPW = BytesPerWord; + + // Allocated size of each space (may not be all occupied) + const size_t ro_alloced = ro_space->capacity_words(Metaspace::NonClassType) * BPW; + const size_t rw_alloced = rw_space->capacity_words(Metaspace::NonClassType) * BPW; + const size_t md_alloced = md_end-md_low; + const size_t mc_alloced = mc_end-mc_low; + const size_t total_alloced = ro_alloced + rw_alloced + md_alloced + mc_alloced; + + // Occupied size of each space. + const size_t ro_bytes = ro_space->used_words(Metaspace::NonClassType) * BPW; + const size_t rw_bytes = rw_space->used_words(Metaspace::NonClassType) * BPW; + const size_t md_bytes = size_t(md_top - md_low); + const size_t mc_bytes = size_t(mc_top - mc_low); + + // Percent of total size + const size_t total_bytes = ro_bytes + rw_bytes + md_bytes + mc_bytes; + const double ro_t_perc = ro_bytes / double(total_bytes) * 100.0; + const double rw_t_perc = rw_bytes / double(total_bytes) * 100.0; + const double md_t_perc = md_bytes / double(total_bytes) * 100.0; + const double mc_t_perc = mc_bytes / double(total_bytes) * 100.0; + + // Percent of fullness of each space + const double ro_u_perc = ro_bytes / double(ro_alloced) * 100.0; + const double rw_u_perc = rw_bytes / double(rw_alloced) * 100.0; + const double md_u_perc = md_bytes / double(md_alloced) * 100.0; + const double mc_u_perc = mc_bytes / double(mc_alloced) * 100.0; + const double total_u_perc = total_bytes / double(total_alloced) * 100.0; + + tty->print_cr(fmt, "ro", ro_bytes, ro_t_perc, ro_alloced, ro_u_perc, ro_space->bottom()); + tty->print_cr(fmt, "rw", rw_bytes, rw_t_perc, rw_alloced, rw_u_perc, rw_space->bottom()); + tty->print_cr(fmt, "md", md_bytes, md_t_perc, md_alloced, md_u_perc, md_low); + tty->print_cr(fmt, "mc", mc_bytes, mc_t_perc, mc_alloced, mc_u_perc, mc_low); + tty->print_cr("total : %9d [100.0%% of total] out of %9d bytes [%4.1f%% used]", + total_bytes, total_alloced, total_u_perc); // Update the vtable pointers in all of the Klass objects in the // heap. They should point to newly generated vtable. diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp index ca3882df0ef..7eb462ecccc 100644 --- a/hotspot/src/share/vm/memory/space.cpp +++ b/hotspot/src/share/vm/memory/space.cpp @@ -40,6 +40,7 @@ #include "runtime/safepoint.hpp" #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" void SpaceMemRegionOopsIterClosure::do_oop(oop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } @@ -658,7 +659,7 @@ void ContiguousSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define ContigSpace_PAR_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ \ void ContiguousSpace::par_oop_iterate(MemRegion mr, OopClosureType* blk) {\ @@ -673,7 +674,7 @@ void ContiguousSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DEFN) #undef ContigSpace_PAR_OOP_ITERATE_DEFN -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void ContiguousSpace::oop_iterate(ExtendedOopClosure* blk) { if (is_empty()) return; diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp index 1dade4a26ed..a434b0a337a 100644 --- a/hotspot/src/share/vm/memory/space.hpp +++ b/hotspot/src/share/vm/memory/space.hpp @@ -34,6 +34,7 @@ #include "oops/markOop.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/prefetch.hpp" +#include "utilities/macros.hpp" #include "utilities/workgroup.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" @@ -884,14 +885,14 @@ class ContiguousSpace: public CompactibleSpace { } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // In support of parallel oop_iterate. #define ContigSpace_PAR_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \ void par_oop_iterate(MemRegion mr, OopClosureType* blk); ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DECL) #undef ContigSpace_PAR_OOP_ITERATE_DECL -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Compaction support virtual void reset_after_compaction() { diff --git a/hotspot/src/share/vm/memory/specialized_oop_closures.hpp b/hotspot/src/share/vm/memory/specialized_oop_closures.hpp index a13660d406a..2aed587f054 100644 --- a/hotspot/src/share/vm/memory/specialized_oop_closures.hpp +++ b/hotspot/src/share/vm/memory/specialized_oop_closures.hpp @@ -26,9 +26,10 @@ #define SHARE_VM_MEMORY_SPECIALIZED_OOP_CLOSURES_HPP #include "runtime/atomic.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_specialized_oop_closures.hpp" -#endif +#endif // INCLUDE_ALL_GCS // The following OopClosure types get specialized versions of // "oop_oop_iterate" that invoke the closures' do_oop methods @@ -80,20 +81,20 @@ class NoHeaderExtendedOopClosure; f(FastScanClosure,_nv) \ f(FilteringClosure,_nv) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) \ f(ParScanWithBarrierClosure,_nv) \ f(ParScanWithoutBarrierClosure,_nv) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f) \ f(NoHeaderExtendedOopClosure,_nv) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \ f(MarkRefsIntoAndScanClosure,_nv) \ f(Par_MarkRefsIntoAndScanClosure,_nv) \ @@ -104,9 +105,9 @@ class NoHeaderExtendedOopClosure; f(CMSKeepAliveClosure,_nv) \ f(CMSInnerParMarkAndPushClosure,_nv) \ FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // We separate these out, because sometime the general one has @@ -120,7 +121,7 @@ class NoHeaderExtendedOopClosure; #define ALL_OOP_OOP_ITERATE_CLOSURES_2(f) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // This macro applies an argument macro to all OopClosures for which we // want specialized bodies of a family of methods related to // "par_oop_iterate". The arguments to f are the same as above. @@ -136,7 +137,7 @@ class NoHeaderExtendedOopClosure; #define ALL_PAR_OOP_ITERATE_CLOSURES(f) \ f(ExtendedOopClosure,_v) \ SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // This macro applies an argument macro to all OopClosures for which we // want specialized bodies of a family of methods related to @@ -155,14 +156,14 @@ class NoHeaderExtendedOopClosure; f(ScanClosure,_nv) \ f(FastScanClosure,_nv) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) \ f(ParScanWithBarrierClosure,_nv) \ f(ParScanWithoutBarrierClosure,_nv) \ FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f) \ SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f) \ diff --git a/hotspot/src/share/vm/memory/tenuredGeneration.cpp b/hotspot/src/share/vm/memory/tenuredGeneration.cpp index f47ea307dd8..1e15d65503a 100644 --- a/hotspot/src/share/vm/memory/tenuredGeneration.cpp +++ b/hotspot/src/share/vm/memory/tenuredGeneration.cpp @@ -33,6 +33,7 @@ #include "memory/tenuredGeneration.hpp" #include "oops/oop.inline.hpp" #include "runtime/java.hpp" +#include "utilities/macros.hpp" TenuredGeneration::TenuredGeneration(ReservedSpace rs, size_t initial_byte_size, int level, @@ -61,7 +62,7 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs, _space_counters = new CSpaceCounters(gen_name, 0, _virtual_space.reserved_size(), _the_space, _gen_counters); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseParNewGC) { typedef ParGCAllocBufferWithBOT* ParGCAllocBufferWithBOTPtr; _alloc_buffers = NEW_C_HEAP_ARRAY(ParGCAllocBufferWithBOTPtr, @@ -77,7 +78,7 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs, } else { _alloc_buffers = NULL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } @@ -339,7 +340,7 @@ void TenuredGeneration::update_counters() { } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS oop TenuredGeneration::par_promote(int thread_num, oop old, markOop m, size_t word_sz) { @@ -423,10 +424,10 @@ void TenuredGeneration::verify_alloc_buffers_clean() { } } -#else // SERIALGC +#else // INCLUDE_ALL_GCS void TenuredGeneration::retire_alloc_buffers_before_full_gc() {} void TenuredGeneration::verify_alloc_buffers_clean() {} -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const { size_t available = max_contiguous_available(); diff --git a/hotspot/src/share/vm/memory/tenuredGeneration.hpp b/hotspot/src/share/vm/memory/tenuredGeneration.hpp index 3a1541e7923..b948a1b0b94 100644 --- a/hotspot/src/share/vm/memory/tenuredGeneration.hpp +++ b/hotspot/src/share/vm/memory/tenuredGeneration.hpp @@ -29,6 +29,7 @@ #include "gc_implementation/shared/gcStats.hpp" #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" +#include "utilities/macros.hpp" // TenuredGeneration models the heap containing old (promoted/tenured) objects. @@ -45,11 +46,11 @@ class TenuredGeneration: public OneContigSpaceCardGeneration { size_t _capacity_at_prologue; size_t _used_at_prologue; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // To support parallel promotion: an array of parallel allocation // buffers, one per thread, initially NULL. ParGCAllocBufferWithBOT** _alloc_buffers; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Retire all alloc buffers before a full GC, so that they will be // re-allocated at the start of the next young GC. @@ -93,14 +94,14 @@ class TenuredGeneration: public OneContigSpaceCardGeneration { size_t size, bool is_tlab); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Overrides. virtual oop par_promote(int thread_num, oop obj, markOop m, size_t word_sz); virtual void par_promote_alloc_undo(int thread_num, HeapWord* obj, size_t word_sz); virtual void par_promote_alloc_done(int thread_num); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Performance Counter support void update_counters(); diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index c528d270c64..a7a6c24bfd2 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,13 +70,14 @@ #include "utilities/events.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Known objects Klass* Universe::_boolArrayKlassObj = NULL; @@ -144,6 +145,7 @@ NarrowPtrStruct Universe::_narrow_oop = { NULL, 0, true }; NarrowPtrStruct Universe::_narrow_klass = { NULL, 0, true }; address Universe::_narrow_ptrs_base; +size_t Universe::_class_metaspace_size; void Universe::basic_type_classes_do(void f(Klass*)) { f(boolArrayKlassObj()); @@ -228,7 +230,7 @@ void Universe::check_alignment(uintx size, uintx alignment, const char* name) { if (size < alignment || size % alignment != 0) { ResourceMark rm; stringStream st; - st.print("Size of %s (%ld bytes) must be aligned to %ld bytes", name, size, alignment); + st.print("Size of %s (" UINTX_FORMAT " bytes) must be aligned to " UINTX_FORMAT " bytes", name, size, alignment); char* error = st.as_string(); vm_exit_during_initialization(error); } @@ -689,8 +691,15 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { // Return specified base for the first request. if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) { base = HeapBaseMinAddress; - } else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) { - if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) && + + // If the total size and the metaspace size are small enough to allow + // UnscaledNarrowOop then just use UnscaledNarrowOop. + } else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop) && + (!UseCompressedKlassPointers || + (((OopEncodingHeapMax - heap_size) + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax))) { + // We don't need to check the metaspace size here because it is always smaller + // than total_size. + if ((total_size <= NarrowOopHeapMax) && (mode == UnscaledNarrowOop) && (Universe::narrow_oop_shift() == 0)) { // Use 32-bits oops without encoding and // place heap's top on the 4Gb boundary @@ -706,14 +715,24 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { base = (OopEncodingHeapMax - heap_size); } } + + // See if ZeroBaseNarrowOop encoding will work for a heap based at + // (KlassEncodingMetaspaceMax - class_metaspace_size()). + } else if (UseCompressedKlassPointers && (mode != HeapBasedNarrowOop) && + (Universe::class_metaspace_size() + HeapBaseMinAddress <= KlassEncodingMetaspaceMax) && + (KlassEncodingMetaspaceMax + heap_size - Universe::class_metaspace_size() <= OopEncodingHeapMax)) { + base = (KlassEncodingMetaspaceMax - Universe::class_metaspace_size()); } else { - // Can't reserve below 32Gb. + // UnscaledNarrowOop encoding didn't work, and no base was found for ZeroBasedOops or + // HeapBasedNarrowOop encoding was requested. So, can't reserve below 32Gb. Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); } + // Set narrow_oop_base and narrow_oop_use_implicit_null_checks // used in ReservedHeapSpace() constructors. // The final values will be set in initialize_heap() below. - if (base != 0 && (base + heap_size) <= OopEncodingHeapMax) { + if ((base != 0) && ((base + heap_size) <= OopEncodingHeapMax) && + (!UseCompressedKlassPointers || (base + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax)) { // Use zero based compressed oops Universe::set_narrow_oop_base(NULL); // Don't need guard page for implicit checks in indexed @@ -740,20 +759,20 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { jint Universe::initialize_heap() { if (UseParallelGC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS Universe::_collectedHeap = new ParallelScavengeHeap(); -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseParallelGC not supported in this VM."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else if (UseG1GC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS G1CollectorPolicy* g1p = new G1CollectorPolicy(); G1CollectedHeap* g1h = new G1CollectedHeap(g1p); Universe::_collectedHeap = g1h; -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseG1GC not supported in java kernel vm."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { GenCollectorPolicy *gc_policy; @@ -761,15 +780,15 @@ jint Universe::initialize_heap() { if (UseSerialGC) { gc_policy = new MarkSweepPolicy(); } else if (UseConcMarkSweepGC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseAdaptiveSizePolicy) { gc_policy = new ASConcurrentMarkSweepPolicy(); } else { gc_policy = new ConcurrentMarkSweepPolicy(); } -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseConcMarkSweepGC not supported in this VM."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { // default old generation gc_policy = new MarkSweepPolicy(); } @@ -796,7 +815,9 @@ jint Universe::initialize_heap() { tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M); } - if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) { + if (((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) || + (UseCompressedKlassPointers && + ((uint64_t)Universe::heap()->base() + Universe::class_metaspace_size() > KlassEncodingMetaspaceMax))) { // Can't reserve heap below 32Gb. // keep the Universe::narrow_oop_base() set in Universe::reserve_heap() Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); @@ -862,8 +883,8 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { // be compressed the same as instances. // Need to round class space size up because it's below the heap and // the actual alignment depends on its size. - size_t metaspace_size = align_size_up(ClassMetaspaceSize, alignment); - size_t total_reserved = align_size_up(heap_size + metaspace_size, alignment); + Universe::set_class_metaspace_size(align_size_up(ClassMetaspaceSize, alignment)); + size_t total_reserved = align_size_up(heap_size + Universe::class_metaspace_size(), alignment); char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr); @@ -904,8 +925,8 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { // compressed oops is greater than the one used for compressed klass // ptrs, a metadata space on top of the heap could become // unreachable. - ReservedSpace class_rs = total_rs.first_part(metaspace_size); - ReservedSpace heap_rs = total_rs.last_part(metaspace_size, alignment); + ReservedSpace class_rs = total_rs.first_part(Universe::class_metaspace_size()); + ReservedSpace heap_rs = total_rs.last_part(Universe::class_metaspace_size(), alignment); Metaspace::initialize_class_space(class_rs); if (UseCompressedOops) { diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index ca7b09c7b19..2bf0b653f58 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -211,6 +211,9 @@ class Universe: AllStatic { static struct NarrowPtrStruct _narrow_klass; static address _narrow_ptrs_base; + // Aligned size of the metaspace. + static size_t _class_metaspace_size; + // array of dummy objects used with +FullGCAlot debug_only(static objArrayOop _fullgc_alot_dummy_array;) // index of next entry to clear @@ -278,6 +281,13 @@ class Universe: AllStatic { static bool reserve_metaspace_helper(bool with_base = false); static ReservedHeapSpace reserve_heap_metaspace(size_t heap_size, size_t alignment, bool& contiguous); + static size_t class_metaspace_size() { + return _class_metaspace_size; + } + static void set_class_metaspace_size(size_t metaspace_size) { + _class_metaspace_size = metaspace_size; + } + // Debugging static int _verify_count; // number of verifies done // True during call to verify(). Should only be set/cleared in verify(). diff --git a/hotspot/src/share/vm/oops/annotations.cpp b/hotspot/src/share/vm/oops/annotations.cpp index 72c5737f056..9e5d6ef3701 100644 --- a/hotspot/src/share/vm/oops/annotations.cpp +++ b/hotspot/src/share/vm/oops/annotations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/annotations.hpp" @@ -114,6 +115,50 @@ void Annotations::print_value_on(outputStream* st) const { st->print("Anotations(" INTPTR_FORMAT ")", this); } +#if INCLUDE_SERVICES +// Size Statistics + +julong Annotations::count_bytes(Array* p) { + julong bytes = 0; + if (p != NULL) { + for (int i = 0; i < p->length(); i++) { + bytes += KlassSizeStats::count_array(p->at(i)); + } + bytes += KlassSizeStats::count_array(p); + } + return bytes; +} + +void Annotations::collect_statistics(KlassSizeStats *sz) const { + sz->_annotations_bytes = sz->count(this); + sz->_class_annotations_bytes = sz->count(class_annotations()); + sz->_fields_annotations_bytes = count_bytes(fields_annotations()); + sz->_methods_annotations_bytes = count_bytes(methods_annotations()); + sz->_methods_parameter_annotations_bytes = + count_bytes(methods_parameter_annotations()); + sz->_methods_default_annotations_bytes = + count_bytes(methods_default_annotations()); + + const Annotations* type_anno = type_annotations(); + if (type_anno != NULL) { + sz->_type_annotations_bytes = sz->count(type_anno); + sz->_type_annotations_bytes += sz->count(type_anno->class_annotations()); + sz->_type_annotations_bytes += count_bytes(type_anno->fields_annotations()); + sz->_type_annotations_bytes += count_bytes(type_anno->methods_annotations()); + } + + sz->_annotations_bytes += + sz->_class_annotations_bytes + + sz->_fields_annotations_bytes + + sz->_methods_annotations_bytes + + sz->_methods_parameter_annotations_bytes + + sz->_methods_default_annotations_bytes + + sz->_type_annotations_bytes; + + sz->_ro_bytes += sz->_annotations_bytes; +} +#endif // INCLUDE_SERVICES + #define BULLET " - " #ifndef PRODUCT diff --git a/hotspot/src/share/vm/oops/annotations.hpp b/hotspot/src/share/vm/oops/annotations.hpp index 07d05467ba1..82d701ac584 100644 --- a/hotspot/src/share/vm/oops/annotations.hpp +++ b/hotspot/src/share/vm/oops/annotations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,6 +34,7 @@ class ClassLoaderData; class outputStream; +class KlassSizeStats; typedef Array AnnotationArray; @@ -82,7 +83,12 @@ class Annotations: public MetaspaceObj { Array* mda, TRAPS); void deallocate_contents(ClassLoaderData* loader_data); DEBUG_ONLY(bool on_stack() { return false; }) // for template + + // Sizing (in words) static int size() { return sizeof(Annotations) / wordSize; } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // Constructor to initialize to null Annotations() : _class_annotations(NULL), @@ -142,7 +148,7 @@ class Annotations: public MetaspaceObj { void set_methods_annotations_of(instanceKlassHandle ik, int idnum, AnnotationArray* anno, Array** md_p, TRAPS); - + static julong count_bytes(Array* p); public: const char* internal_name() const { return "{constant pool}"; } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 38a5340e366..f37a4d500ae 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,6 +106,14 @@ class ArrayKlass: public Klass { static int header_size() { return sizeof(ArrayKlass)/HeapWordSize; } static int static_size(int header_size); +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const { + Klass::collect_statistics(sz); + // Do nothing for now, but remember to modify if you add new + // stuff to ArrayKlass. + } +#endif + // Java vtable klassVtable* vtable() const; // return new klassVtable int vtable_length() const { return _vtable_len; } diff --git a/hotspot/src/share/vm/oops/constMethod.cpp b/hotspot/src/share/vm/oops/constMethod.cpp index 79c10c0e62a..3358d225e2a 100644 --- a/hotspot/src/share/vm/oops/constMethod.cpp +++ b/hotspot/src/share/vm/oops/constMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "interpreter/interpreter.hpp" #include "memory/gcLocker.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "oops/constMethod.hpp" #include "oops/method.hpp" @@ -330,6 +331,18 @@ void ConstMethod::print_value_on(outputStream* st) const { method()->print_value_on(st); } +#if INCLUDE_SERVICES +// Size Statistics +void ConstMethod::collect_statistics(KlassSizeStats *sz) const { + int n1, n2, n3; + sz->_const_method_bytes += (n1 = sz->count(this)); + sz->_bytecode_bytes += (n2 = code_size()); + sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data())); + + sz->_method_all_bytes += n1 + n3; // note: n2 is part of n3 + sz->_ro_bytes += n1 + n3; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 08c650278e6..12a36c24470 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,9 +122,10 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC { class MethodParametersElement VALUE_OBJ_CLASS_SPEC { public: u2 name_cp_index; - u4 flags; + u2 flags; }; +class KlassSizeStats; class ConstMethod : public MetaspaceObj { friend class VMStructs; @@ -315,6 +316,9 @@ public: int size() const { return _constMethod_size;} void set_constMethod_size(int size) { _constMethod_size = size; } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // code size int code_size() const { return _code_size; } diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index ff8472d3d79..1c21420c29a 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,16 +25,17 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/constantPool.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" -#include "prims/jvmtiRedefineClasses.hpp" #include "runtime/fieldType.hpp" #include "runtime/init.hpp" #include "runtime/javaCalls.hpp" @@ -65,11 +66,10 @@ ConstantPool::ConstantPool(Array* tags) { set_operands(NULL); set_pool_holder(NULL); set_flags(0); + // only set to non-zero if constant pool is merged by RedefineClasses - set_orig_length(0); + set_version(0); set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); - // all fields are initialized; needed for GC - set_on_stack(false); // initialize tag array int length = tags->length(); @@ -100,18 +100,6 @@ void ConstantPool::release_C_heap_structures() { set_lock(NULL); } -void ConstantPool::set_flag_at(FlagBit fb) { - const int MAX_STATE_CHANGES = 2; - for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) { - int oflags = _flags; - int nflags = oflags | (1 << (int)fb); - if (Atomic::cmpxchg(nflags, &_flags, oflags) == oflags) - return; - } - assert(false, "failed to cmpxchg flags"); - _flags |= (1 << (int)fb); // better than nothing -} - objArrayOop ConstantPool::resolved_references() const { return (objArrayOop)JNIHandles::resolve(_resolved_references); } @@ -1111,32 +1099,9 @@ bool ConstantPool::compare_entry_to(int index1, constantPoolHandle cp2, } // end compare_entry_to() -// Copy this constant pool's entries at start_i to end_i (inclusive) -// to the constant pool to_cp's entries starting at to_i. A total of -// (end_i - start_i) + 1 entries are copied. -void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, - constantPoolHandle to_cp, int to_i, TRAPS) { - - int dest_i = to_i; // leave original alone for debug purposes - - for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) { - copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK); - - switch (from_cp->tag_at(src_i).value()) { - case JVM_CONSTANT_Double: - case JVM_CONSTANT_Long: - // double and long take two constant pool entries - src_i += 2; - dest_i += 2; - break; - - default: - // all others take one constant pool entry - src_i++; - dest_i++; - break; - } - } +void ConstantPool::copy_operands(constantPoolHandle from_cp, + constantPoolHandle to_cp, + TRAPS) { int from_oplen = operand_array_length(from_cp->operands()); int old_oplen = operand_array_length(to_cp->operands()); @@ -1164,7 +1129,7 @@ void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int (len = old_off) * sizeof(u2)); fillp += len; // first part of src - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(0), + Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(0), new_operands->adr_at(fillp), (len = from_off) * sizeof(u2)); fillp += len; @@ -1174,7 +1139,7 @@ void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int (len = old_len - old_off) * sizeof(u2)); fillp += len; // second part of src - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(from_off), + Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(from_off), new_operands->adr_at(fillp), (len = from_len - from_off) * sizeof(u2)); fillp += len; @@ -1192,8 +1157,39 @@ void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int to_cp->set_operands(new_operands); } } +} // end copy_operands() -} // end copy_cp_to() + +// Copy this constant pool's entries at start_i to end_i (inclusive) +// to the constant pool to_cp's entries starting at to_i. A total of +// (end_i - start_i) + 1 entries are copied. +void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, + constantPoolHandle to_cp, int to_i, TRAPS) { + + + int dest_i = to_i; // leave original alone for debug purposes + + for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) { + copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK); + + switch (from_cp->tag_at(src_i).value()) { + case JVM_CONSTANT_Double: + case JVM_CONSTANT_Long: + // double and long take two constant pool entries + src_i += 2; + dest_i += 2; + break; + + default: + // all others take one constant pool entry + src_i++; + dest_i++; + break; + } + } + copy_operands(from_cp, to_cp, CHECK); + +} // end copy_cp_to_impl() // Copy this constant pool's entry at from_i to the constant pool @@ -1755,7 +1751,11 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, void ConstantPool::set_on_stack(const bool value) { - _on_stack = value; + if (value) { + _flags |= _on_stack; + } else { + _flags &= ~_on_stack; + } if (value) MetadataOnStackMark::record(this); } @@ -1827,6 +1827,7 @@ void ConstantPool::print_on(outputStream* st) const { if (has_pseudo_string()) st->print(" has_pseudo_string"); if (has_invokedynamic()) st->print(" has_invokedynamic"); if (has_preresolution()) st->print(" has_preresolution"); + if (on_stack()) st->print(" on_stack"); st->cr(); } if (pool_holder() != NULL) { @@ -1954,6 +1955,20 @@ void ConstantPool::print_value_on(outputStream* st) const { } } +#if INCLUDE_SERVICES +// Size Statistics +void ConstantPool::collect_statistics(KlassSizeStats *sz) const { + sz->_cp_all_bytes += (sz->_cp_bytes = sz->count(this)); + sz->_cp_all_bytes += (sz->_cp_tags_bytes = sz->count_array(tags())); + sz->_cp_all_bytes += (sz->_cp_cache_bytes = sz->count(cache())); + sz->_cp_all_bytes += (sz->_cp_operands_bytes = sz->count_array(operands())); + sz->_cp_all_bytes += (sz->_cp_refmap_bytes = sz->count_array(reference_map())); + + sz->_ro_bytes += sz->_cp_operands_bytes + sz->_cp_tags_bytes + + sz->_cp_refmap_bytes; + sz->_rw_bytes += sz->_cp_bytes + sz->_cp_cache_bytes; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 768cd39a65c..92ae90f20a6 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,6 +80,7 @@ class CPSlot VALUE_OBJ_CLASS_SPEC { } }; +class KlassSizeStats; class ConstantPool : public Metadata { friend class VMStructs; friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast @@ -95,16 +96,21 @@ class ConstantPool : public Metadata { jobject _resolved_references; Array* _reference_map; - int _flags; // a few header bits to describe contents for GC - int _length; // number of elements in the array + enum { + _has_invokedynamic = 1, // Flags + _has_pseudo_string = 2, + _has_preresolution = 4, + _on_stack = 8 + }; - bool _on_stack; // Redefined method still executing refers to this constant pool. + int _flags; // old fashioned bit twiddling + int _length; // number of elements in the array union { // set for CDS to restore resolved references int _resolved_reference_length; - // only set to non-zero if constant pool is merged by RedefineClasses - int _orig_length; + // keeps version number for redefined classes (used in backtrace) + int _version; } _saved; Monitor* _lock; @@ -115,17 +121,8 @@ class ConstantPool : public Metadata { void set_operands(Array* operands) { _operands = operands; } - enum FlagBit { - FB_has_invokedynamic = 1, - FB_has_pseudo_string = 2, - FB_has_preresolution = 3 - }; - - int flags() const { return _flags; } - void set_flags(int f) { _flags = f; } - bool flag_at(FlagBit fb) const { return (_flags & (1 << (int)fb)) != 0; } - void set_flag_at(FlagBit fb); - // no clear_flag_at function; they only increase + int flags() const { return _flags; } + void set_flags(int f) { _flags = f; } private: intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); } @@ -178,18 +175,20 @@ class ConstantPool : public Metadata { Array* tags() const { return _tags; } Array* operands() const { return _operands; } - bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); } - bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); } - bool has_preresolution() const { return flag_at(FB_has_preresolution); } - void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); } - void set_invokedynamic() { set_flag_at(FB_has_invokedynamic); } - void set_preresolution() { set_flag_at(FB_has_preresolution); } + bool has_invokedynamic() const { return (_flags & _has_invokedynamic) != 0; } + void set_has_invokedynamic() { _flags |= _has_invokedynamic; } + + bool has_pseudo_string() const { return (_flags & _has_pseudo_string) != 0; } + void set_has_pseudo_string() { _flags |= _has_pseudo_string; } + + bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } + void set_has_preresolution() { _flags |= _has_preresolution; } // Redefine classes support. If a method refering to this constant pool // is on the executing stack, or as a handle in vm code, this constant pool // can't be removed from the set of previous versions saved in the instance // class. - bool on_stack() const { return _on_stack; } + bool on_stack() const { return (_flags &_on_stack) != 0; } void set_on_stack(const bool value); // Klass holding pool @@ -457,7 +456,7 @@ class ConstantPool : public Metadata { void pseudo_string_at_put(int which, int obj_index, oop x) { assert(EnableInvokeDynamic, ""); - set_pseudo_string(); // mark header + set_has_pseudo_string(); // mark header assert(tag_at(which).is_string(), "Corrupted constant pool"); string_at_put(which, obj_index, x); // this works just fine } @@ -686,9 +685,13 @@ class ConstantPool : public Metadata { return 0 <= index && index < length(); } + // Sizing (in words) static int header_size() { return sizeof(ConstantPool)/HeapWordSize; } static int size(int length) { return align_object_size(header_size() + length); } int size() const { return size(length()); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif friend class ClassFileParser; friend class SystemDictionary; @@ -783,9 +786,13 @@ class ConstantPool : public Metadata { } static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS); static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS); + static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS); int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS); - int orig_length() const { return _saved._orig_length; } - void set_orig_length(int orig_length) { _saved._orig_length = orig_length; } + int version() const { return _saved._version; } + void set_version(int version) { _saved._version = version; } + void increment_and_save_version(int version) { + _saved._version = version >= 0 ? (version + 1) : version; // keep overflow + } void set_resolved_reference_length(int length) { _saved._resolved_reference_length = length; } int resolved_reference_length() const { return _saved._resolved_reference_length; } diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index 06c70cd02e3..7d6d36b6881 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -33,9 +33,10 @@ #include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/methodHandles.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS # include "gc_implementation/parallelScavenge/psPromotionManager.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Implememtation of ConstantPoolCacheEntry diff --git a/hotspot/src/share/vm/oops/fieldInfo.hpp b/hotspot/src/share/vm/oops/fieldInfo.hpp index ee4af47204d..331dc05f37c 100644 --- a/hotspot/src/share/vm/oops/fieldInfo.hpp +++ b/hotspot/src/share/vm/oops/fieldInfo.hpp @@ -43,14 +43,29 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { public: // fields // Field info extracted from the class file and stored - // as an array of 7 shorts + // as an array of 6 shorts. + +#define FIELDINFO_TAG_SIZE 2 +#define FIELDINFO_TAG_BLANK 0 +#define FIELDINFO_TAG_OFFSET 1 +#define FIELDINFO_TAG_TYPE_PLAIN 2 +#define FIELDINFO_TAG_TYPE_CONTENDED 3 +#define FIELDINFO_TAG_MASK 3 + + // Packed field has the tag, and can be either of: + // hi bits <--------------------------- lo bits + // |---------high---------|---------low---------| + // ..........................................00 - blank + // [------------------offset----------------]01 - real field offset + // ......................[-------type-------]10 - plain field with type + // [--contention_group--][-------type-------]11 - contended field with type and contention group enum FieldOffset { access_flags_offset = 0, name_index_offset = 1, signature_index_offset = 2, initval_index_offset = 3, - low_offset = 4, - high_offset = 5, + low_packed_offset = 4, + high_packed_offset = 5, field_slots = 6 }; @@ -76,17 +91,90 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { void initialize(u2 access_flags, u2 name_index, u2 signature_index, - u2 initval_index, - u4 offset) { + u2 initval_index) { _shorts[access_flags_offset] = access_flags; _shorts[name_index_offset] = name_index; _shorts[signature_index_offset] = signature_index; _shorts[initval_index_offset] = initval_index; - set_offset(offset); + _shorts[low_packed_offset] = 0; + _shorts[high_packed_offset] = 0; } u2 access_flags() const { return _shorts[access_flags_offset]; } - u4 offset() const { return build_int_from_shorts(_shorts[low_offset], _shorts[high_offset]); } + u4 offset() const { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_OFFSET: + return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE; +#ifndef PRODUCT + case FIELDINFO_TAG_TYPE_PLAIN: + ShouldNotReachHere2("Asking offset for the plain type field"); + case FIELDINFO_TAG_TYPE_CONTENDED: + ShouldNotReachHere2("Asking offset for the contended type field"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Asking offset for the blank field"); +#endif + } + ShouldNotReachHere(); + return 0; + } + + bool is_contended() const { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_TYPE_PLAIN: + return false; + case FIELDINFO_TAG_TYPE_CONTENDED: + return true; +#ifndef PRODUCT + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Asking contended flag for the field with offset"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Asking contended flag for the blank field"); +#endif + } + ShouldNotReachHere(); + return false; + } + + u2 contended_group() const { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_TYPE_PLAIN: + return 0; + case FIELDINFO_TAG_TYPE_CONTENDED: + return _shorts[high_packed_offset]; +#ifndef PRODUCT + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Asking the contended group for the field with offset"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Asking the contended group for the blank field"); +#endif + } + ShouldNotReachHere(); + return 0; + } + + u2 allocation_type() const { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_TYPE_PLAIN: + case FIELDINFO_TAG_TYPE_CONTENDED: + return (lo >> FIELDINFO_TAG_SIZE); +#ifndef PRODUCT + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Asking the field type for field with offset"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Asking the field type for the blank field"); +#endif + } + ShouldNotReachHere(); + return 0; + } + + bool is_offset_set() const { + return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET; + } Symbol* name(constantPoolHandle cp) const { int index = name_index(); @@ -106,8 +194,46 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } void set_offset(u4 val) { - _shorts[low_offset] = extract_low_short_from_int(val); - _shorts[high_offset] = extract_high_short_from_int(val); + val = val << FIELDINFO_TAG_SIZE; // make room for tag + _shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET; + _shorts[high_packed_offset] = extract_high_short_from_int(val); + } + + void set_allocation_type(int type) { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_BLANK: + _shorts[low_packed_offset] = ((type << FIELDINFO_TAG_SIZE)) & 0xFFFF; + _shorts[low_packed_offset] &= ~FIELDINFO_TAG_MASK; + _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_PLAIN; + return; +#ifndef PRODUCT + case FIELDINFO_TAG_TYPE_PLAIN: + case FIELDINFO_TAG_TYPE_CONTENDED: + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Setting the field type with overwriting"); +#endif + } + ShouldNotReachHere(); + } + + void set_contended_group(u2 val) { + u2 lo = _shorts[low_packed_offset]; + switch(lo & FIELDINFO_TAG_MASK) { + case FIELDINFO_TAG_TYPE_PLAIN: + _shorts[low_packed_offset] |= FIELDINFO_TAG_TYPE_CONTENDED; + _shorts[high_packed_offset] = val; + return; +#ifndef PRODUCT + case FIELDINFO_TAG_TYPE_CONTENDED: + ShouldNotReachHere2("Overwriting contended group"); + case FIELDINFO_TAG_BLANK: + ShouldNotReachHere2("Setting contended group for the blank field"); + case FIELDINFO_TAG_OFFSET: + ShouldNotReachHere2("Setting contended group for field with offset"); +#endif + } + ShouldNotReachHere(); } bool is_internal() const { diff --git a/hotspot/src/share/vm/oops/fieldStreams.hpp b/hotspot/src/share/vm/oops/fieldStreams.hpp index adde764127b..acc590c970c 100644 --- a/hotspot/src/share/vm/oops/fieldStreams.hpp +++ b/hotspot/src/share/vm/oops/fieldStreams.hpp @@ -160,9 +160,26 @@ class FieldStreamBase : public StackObj { return field()->offset(); } + int allocation_type() const { + return field()->allocation_type(); + } + void set_offset(int offset) { field()->set_offset(offset); } + + bool is_offset_set() const { + return field()->is_offset_set(); + } + + bool is_contended() const { + return field()->is_contended(); + } + + int contended_group() const { + return field()->contended_group(); + } + }; // Iterate over only the internal fields diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp index def7d10e595..507206fc854 100644 --- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp @@ -36,12 +36,13 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/parOopClosures.inline.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define if_do_metadata_checked(closure, nv_suffix) \ /* Make sure the non-virtual and the virtual versions match. */ \ @@ -73,7 +74,7 @@ oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { return size; \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceClassLoaderKlass:: \ @@ -83,7 +84,7 @@ oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \ return size; \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -111,10 +112,10 @@ oop_oop_iterate##nv_suffix##_m(oop obj, ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m) @@ -129,7 +130,7 @@ void InstanceClassLoaderKlass::oop_follow_contents(oop obj) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceClassLoaderKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { InstanceKlass::oop_follow_contents(cm, obj); @@ -155,5 +156,5 @@ int InstanceClassLoaderKlass::oop_update_pointers(ParCompactionManager* cm, oop } return size_helper(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp index c9f7f026a0e..d93f2a5c32a 100644 --- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP #include "oops/instanceKlass.hpp" +#include "utilities/macros.hpp" // An InstanceClassLoaderKlass is a specialization of the InstanceKlass. It does // not add any field. It is added to walk the dependencies for the class loader @@ -61,13 +62,13 @@ public: ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Garbage collection void oop_follow_contents(oop obj); diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index d123641a0c7..4af6e32063d 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "interpreter/rewriter.hpp" #include "jvmtifiles/jvmti.h" #include "memory/genOopClosures.inline.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/fieldStreams.hpp" @@ -55,7 +56,8 @@ #include "runtime/thread.inline.hpp" #include "services/threadService.hpp" #include "utilities/dtrace.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -66,7 +68,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #endif @@ -2042,7 +2044,7 @@ void InstanceKlass::oop_follow_contents(oop obj) { assert_is_in_closed_subset) } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert(obj != NULL, "can't follow the content of NULL object"); @@ -2054,7 +2056,7 @@ void InstanceKlass::oop_follow_contents(ParCompactionManager* cm, PSParallelCompact::mark_and_push(cm, p), \ assert_is_in) } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // closure's do_metadata() method dictates whether the given closure should be // applied to the klass ptr in the object header. @@ -2082,7 +2084,7 @@ int InstanceKlass::oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) return size_helper(); \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj, \ @@ -2100,7 +2102,7 @@ int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj, assert_is_in_closed_subset) \ return size_helper(); \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ \ @@ -2124,10 +2126,10 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceKlass::oop_adjust_pointers(oop obj) { int size = size_helper(); @@ -2139,7 +2141,7 @@ int InstanceKlass::oop_adjust_pointers(oop obj) { return size; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { InstanceKlass_OOP_MAP_REVERSE_ITERATE( \ obj, \ @@ -2159,7 +2161,7 @@ int InstanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { assert(is_loader_alive(is_alive), "this klass should be live"); @@ -2890,11 +2892,7 @@ void InstanceKlass::oop_print_on(oop obj, outputStream* st) { st->print(BULLET"fake entry for mirror: "); mirrored_klass->print_value_on_maybe_null(st); st->cr(); - st->print(BULLET"fake entry resolved_constructor: "); - Method* ctor = java_lang_Class::resolved_constructor(obj); - ctor->print_value_on_maybe_null(st); Klass* array_klass = java_lang_Class::array_klass(obj); - st->cr(); st->print(BULLET"fake entry for array: "); array_klass->print_value_on_maybe_null(st); st->cr(); @@ -2964,6 +2962,52 @@ const char* InstanceKlass::internal_name() const { return external_name(); } +#if INCLUDE_SERVICES +// Size Statistics +void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { + Klass::collect_statistics(sz); + + sz->_inst_size = HeapWordSize * size_helper(); + sz->_vtab_bytes = HeapWordSize * align_object_offset(vtable_length()); + sz->_itab_bytes = HeapWordSize * align_object_offset(itable_length()); + sz->_nonstatic_oopmap_bytes = HeapWordSize * + ((is_interface() || is_anonymous()) ? + align_object_offset(nonstatic_oop_map_size()) : + nonstatic_oop_map_size()); + + int n = 0; + n += (sz->_methods_array_bytes = sz->count_array(methods())); + n += (sz->_method_ordering_bytes = sz->count_array(method_ordering())); + n += (sz->_local_interfaces_bytes = sz->count_array(local_interfaces())); + n += (sz->_transitive_interfaces_bytes = sz->count_array(transitive_interfaces())); + n += (sz->_signers_bytes = sz->count_array(signers())); + n += (sz->_fields_bytes = sz->count_array(fields())); + n += (sz->_inner_classes_bytes = sz->count_array(inner_classes())); + sz->_ro_bytes += n; + + const ConstantPool* cp = constants(); + if (cp) { + cp->collect_statistics(sz); + } + + const Annotations* anno = annotations(); + if (anno) { + anno->collect_statistics(sz); + } + + const Array* methods_array = methods(); + if (methods()) { + for (int i = 0; i < methods_array->length(); i++) { + Method* method = methods_array->at(i); + if (method) { + sz->_method_count ++; + method->collect_statistics(sz); + } + } + } +} +#endif // INCLUDE_SERVICES + // Verification class VerifyFieldClosure: public OopClosure { diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 0d173faa510..025da12825d 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ #include "runtime/os.hpp" #include "utilities/accessFlags.hpp" #include "utilities/bitMap.inline.hpp" +#include "utilities/macros.hpp" // An InstanceKlass is the VM level representation of a Java class. // It contains all information needed for at class at execution runtime. @@ -225,12 +226,17 @@ class InstanceKlass: public Klass { u2 _java_fields_count; // The number of declared Java fields int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks + // _is_marked_dependent can be set concurrently, thus cannot be part of the + // _misc_flags. bool _is_marked_dependent; // used for marking during flushing and deoptimization + enum { _misc_rewritten = 1 << 0, // methods rewritten. _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops _misc_should_verify_class = 1 << 2, // allow caching of preverification - _misc_is_anonymous = 1 << 3 // has embedded _inner_classes field + _misc_is_anonymous = 1 << 3, // has embedded _inner_classes field + _misc_is_contended = 1 << 4, // marked with contended annotation + _misc_has_default_methods = 1 << 5 // class/superclass/implemented interfaces has default methods }; u2 _misc_flags; u2 _minor_version; // minor version number of class file @@ -251,12 +257,18 @@ class InstanceKlass: public Klass { // JVMTI fields can be moved to their own structure - see 6315920 unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH jint _cached_class_file_len; // JVMTI: length of above - JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration - - // true if class, superclass, or implemented interfaces have default methods - bool _has_default_methods; volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change + + // Class states are defined as ClassState (see above). + // Place the _init_state here to utilize the unused 2-byte after + // _idnum_allocated_count. + u1 _init_state; // state of class + u1 _reference_type; // reference type + + + JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration + // Method array. Array* _methods; // Interface (Klass*s) this class declares locally to implement. @@ -280,13 +292,6 @@ class InstanceKlass: public Klass { // ... Array* _fields; - // Class states are defined as ClassState (see above). - // Place the _init_state here to utilize the unused 2-byte after - // _idnum_allocated_count. - u1 _init_state; // state of class - - u1 _reference_type; // reference type - // embedded Java vtable follows here // embedded Java itables follows here // embedded static fields follows here @@ -550,6 +555,17 @@ class InstanceKlass: public Klass { return is_anonymous() ? java_mirror() : class_loader(); } + bool is_contended() const { + return (_misc_flags & _misc_is_contended) != 0; + } + void set_is_contended(bool value) { + if (value) { + _misc_flags |= _misc_is_contended; + } else { + _misc_flags &= ~_misc_is_contended; + } + } + // signers objArrayOop signers() const { return _signers; } void set_signers(objArrayOop s) { klass_oop_store((oop*)&_signers, s); } @@ -616,8 +632,16 @@ class InstanceKlass: public Klass { return _jvmti_cached_class_field_map; } - bool has_default_methods() const { return _has_default_methods; } - void set_has_default_methods(bool b) { _has_default_methods = b; } + bool has_default_methods() const { + return (_misc_flags & _misc_has_default_methods) != 0; + } + void set_has_default_methods(bool b) { + if (b) { + _misc_flags |= _misc_has_default_methods; + } else { + _misc_flags &= ~_misc_has_default_methods; + } + } // for adding methods, ConstMethod::UNSET_IDNUM means no more ids available inline u2 next_method_idnum(); @@ -804,6 +828,9 @@ class InstanceKlass: public Klass { is_interface(), is_anonymous()); } +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const; +#endif static int vtable_start_offset() { return header_size(); } static int vtable_length_offset() { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; } @@ -910,13 +937,13 @@ class InstanceKlass: public Klass { ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS u2 idnum_allocated_count() const { return _idnum_allocated_count; } private: diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp index 4e63075c423..3eabba70a1a 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp @@ -35,7 +35,8 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -45,7 +46,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::_offset_of_static_fields = 0; @@ -168,7 +169,7 @@ void InstanceMirrorKlass::oop_follow_contents(oop obj) { assert_is_in_closed_subset) } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceMirrorKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { InstanceKlass::oop_follow_contents(cm, obj); @@ -189,7 +190,7 @@ void InstanceMirrorKlass::oop_follow_contents(ParCompactionManager* cm, PSParallelCompact::mark_and_push(cm, p), \ assert_is_in) } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::oop_adjust_pointers(oop obj) { int size = oop_size(obj); @@ -262,7 +263,7 @@ oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { } \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceMirrorKlass:: \ @@ -278,7 +279,7 @@ oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix); \ } \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -310,14 +311,14 @@ oop_oop_iterate##nv_suffix##_m(oop obj, ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceMirrorKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { // Note that we don't have to follow the mirror -> klass pointer, since all // klasses that are dirty will be scavenged when we iterate over the @@ -353,7 +354,7 @@ int InstanceMirrorKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) assert_nothing) return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::instance_size(KlassHandle k) { if (k() != NULL && k->oop_is_instance()) { diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp index db1d8de2565..38f2dc81787 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp @@ -28,6 +28,7 @@ #include "classfile/systemDictionary.hpp" #include "oops/instanceKlass.hpp" #include "runtime/handles.hpp" +#include "utilities/macros.hpp" // An InstanceMirrorKlass is a specialized InstanceKlass for // java.lang.Class instances. These instances are special because @@ -107,13 +108,13 @@ class InstanceMirrorKlass: public InstanceKlass { ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS }; #endif // SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.cpp b/hotspot/src/share/vm/oops/instanceRefKlass.cpp index 1784609e3f2..cb5f8965521 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp @@ -33,7 +33,8 @@ #include "oops/instanceRefKlass.hpp" #include "oops/oop.inline.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp" @@ -42,7 +43,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS template void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) { @@ -120,7 +121,7 @@ void InstanceRefKlass::oop_follow_contents(oop obj) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template void specialized_oop_follow_contents(InstanceRefKlass* ref, ParCompactionManager* cm, @@ -194,7 +195,7 @@ void InstanceRefKlass::oop_follow_contents(ParCompactionManager* cm, specialized_oop_follow_contents(this, cm, obj); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifdef ASSERT template void trace_reference_gc(const char *s, oop obj, @@ -317,7 +318,7 @@ oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { } \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceRefKlass:: \ @@ -333,7 +334,7 @@ oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \ } \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -354,14 +355,14 @@ oop_oop_iterate##nv_suffix##_m(oop obj, ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template void specialized_oop_push_contents(InstanceRefKlass *ref, PSPromotionManager* pm, oop obj) { @@ -444,7 +445,7 @@ int InstanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { } return size_helper(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) { // Clear the nonstatic oop-map entries corresponding to referent diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.hpp b/hotspot/src/share/vm/oops/instanceRefKlass.hpp index fd565ecd823..d8771608f73 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_OOPS_INSTANCEREFKLASS_HPP #include "oops/instanceKlass.hpp" +#include "utilities/macros.hpp" // An InstanceRefKlass is a specialized InstanceKlass for Java // classes that are subclasses of java/lang/ref/Reference. @@ -83,13 +84,13 @@ class InstanceRefKlass: public InstanceKlass { ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock); static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock); diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 21bfb6bda69..341f60c3fe8 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "classfile/vmSymbols.hpp" #include "gc_implementation/shared/markSweep.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -37,11 +38,12 @@ #include "oops/oop.inline2.hpp" #include "runtime/atomic.hpp" #include "utilities/stack.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" -#endif +#endif // INCLUDE_ALL_GCS void Klass::set_name(Symbol* n) { _name = n; @@ -624,6 +626,17 @@ void Klass::oop_print_value_on(oop obj, outputStream* st) { obj->print_address_on(st); } +#if INCLUDE_SERVICES +// Size Statistics +void Klass::collect_statistics(KlassSizeStats *sz) const { + sz->_klass_bytes = sz->count(this); + sz->_mirror_bytes = sz->count(java_mirror()); + sz->_secondary_supers_bytes = sz->count_array(secondary_supers()); + + sz->_ro_bytes += sz->_secondary_supers_bytes; + sz->_rw_bytes += sz->_klass_bytes + sz->_mirror_bytes; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index be5d0c5293d..803f4da2737 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,11 +35,12 @@ #include "runtime/orderAccess.hpp" #include "trace/traceMacros.hpp" #include "utilities/accessFlags.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp" #include "gc_implementation/g1/g1OopClosures.hpp" #include "gc_implementation/parNew/parOopClosures.hpp" -#endif +#endif // INCLUDE_ALL_GCS // // A Klass provides: @@ -75,11 +76,11 @@ // [class_loader_data] // [modifier_flags] // [access_flags ] -// [verify_count ] - not in product -// [alloc_count ] // [last_biased_lock_bulk_revocation_time] (64 bits) // [prototype_header] // [biased_lock_revocation_count] +// [verify_count ] - not in product +// [alloc_count ] // [_modified_oops] // [_accumulated_modified_oops] // [trace_id] @@ -91,6 +92,7 @@ template class GrowableArray; class ClassLoaderData; class klassVtable; class ParCompactionManager; +class KlassSizeStats; class Klass : public Metadata { friend class VMStructs; @@ -164,18 +166,18 @@ class Klass : public Metadata { jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. -#ifndef PRODUCT - int _verify_count; // to avoid redundant verifies -#endif - - juint _alloc_count; // allocation profiling support - // Biased locking implementation and statistics // (the 64-bit chunk goes first, to avoid some fragmentation) jlong _last_biased_lock_bulk_revocation_time; markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type jint _biased_lock_revocation_count; +#ifndef PRODUCT + int _verify_count; // to avoid redundant verifies +#endif + + juint _alloc_count; // allocation profiling support + TRACE_DEFINE_KLASS_TRACE_ID; // Remembered sets support for the oops in the klasses. @@ -477,6 +479,9 @@ class Klass : public Metadata { // Size of klass in word size. virtual int size() const = 0; +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const; +#endif // Returns the Java name for a class (Resource allocated) // For arrays, this returns the name of the element with a leading '['. @@ -625,13 +630,13 @@ class Klass : public Metadata { return oop_oop_iterate(obj, blk); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // In case we don't have a specialized backward scanner use forward // iteration. virtual int oop_oop_iterate_backwards_v(oop obj, ExtendedOopClosure* blk) { return oop_oop_iterate_v(obj, blk); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Iterates "blk" over all the oops in "obj" (of type "this") within "mr". // (I don't see why the _m should be required, but without it the Solaris @@ -663,7 +668,7 @@ class Klass : public Metadata { SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL) SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define Klass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ virtual int oop_oop_iterate_backwards##nv_suffix(oop obj, \ OopClosureType* blk) { \ @@ -673,7 +678,7 @@ class Klass : public Metadata { SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL) SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS virtual void array_klasses_do(void f(Klass* k)) {} virtual void with_array_klasses_do(void f(Klass* k)); diff --git a/hotspot/src/share/vm/oops/klassPS.hpp b/hotspot/src/share/vm/oops/klassPS.hpp index 0aa7a580d4c..5fb17b6e801 100644 --- a/hotspot/src/share/vm/oops/klassPS.hpp +++ b/hotspot/src/share/vm/oops/klassPS.hpp @@ -27,7 +27,9 @@ // Expands to Parallel Scavenge and Parallel Old declarations -#ifndef SERIALGC +#include "utilities/macros.hpp" + +#if INCLUDE_ALL_GCS #define PARALLEL_GC_DECLS \ virtual void oop_push_contents(PSPromotionManager* pm, oop obj); \ /* Parallel Old GC support \ @@ -44,9 +46,9 @@ virtual void oop_push_contents(PSPromotionManager* pm, oop obj) = 0; \ virtual void oop_follow_contents(ParCompactionManager* cm, oop obj) = 0; \ virtual int oop_update_pointers(ParCompactionManager* cm, oop obj) = 0; -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define PARALLEL_GC_DECLS #define PARALLEL_GC_DECLS_PV -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_KLASSPS_HPP diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 936090f50c0..110148a72d5 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "code/debugInfoRec.hpp" #include "gc_interface/collectedHeap.inline.hpp" @@ -33,6 +34,7 @@ #include "interpreter/oopMapCache.hpp" #include "memory/gcLocker.hpp" #include "memory/generation.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/constMethod.hpp" @@ -41,7 +43,6 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "prims/jvmtiExport.hpp" -#include "prims/jvmtiRedefineClasses.hpp" #include "prims/methodHandles.hpp" #include "prims/nativeLookup.hpp" #include "runtime/arguments.hpp" @@ -699,7 +700,7 @@ void Method::set_signature_handler(address handler) { } -void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report) { +void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason) { if (PrintCompilation && report) { ttyLocker ttyl; tty->print("made not %scompilable on ", is_osr ? "OSR " : ""); @@ -713,14 +714,21 @@ void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report) } this->print_short_name(tty); int size = this->code_size(); - if (size > 0) + if (size > 0) { tty->print(" (%d bytes)", size); + } + if (reason != NULL) { + tty->print(" %s", reason); + } tty->cr(); } if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) { ttyLocker ttyl; xtty->begin_elem("make_not_%scompilable thread='" UINTX_FORMAT "'", is_osr ? "osr_" : "", os::current_thread_id()); + if (reason != NULL) { + xtty->print(" reason=\'%s\'", reason); + } xtty->method(this); xtty->stamp(); xtty->end_elem(); @@ -742,8 +750,8 @@ bool Method::is_not_compilable(int comp_level) const { } // call this when compiler finds that this method is not compilable -void Method::set_not_compilable(int comp_level, bool report) { - print_made_not_compilable(comp_level, /*is_osr*/ false, report); +void Method::set_not_compilable(int comp_level, bool report, const char* reason) { + print_made_not_compilable(comp_level, /*is_osr*/ false, report, reason); if (comp_level == CompLevel_all) { set_not_c1_compilable(); set_not_c2_compilable(); @@ -768,8 +776,8 @@ bool Method::is_not_osr_compilable(int comp_level) const { return false; } -void Method::set_not_osr_compilable(int comp_level, bool report) { - print_made_not_compilable(comp_level, /*is_osr*/ true, report); +void Method::set_not_osr_compilable(int comp_level, bool report, const char* reason) { + print_made_not_compilable(comp_level, /*is_osr*/ true, report, reason); if (comp_level == CompLevel_all) { set_not_c1_osr_compilable(); set_not_c2_osr_compilable(); @@ -1027,7 +1035,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, cp->set_pool_holder(InstanceKlass::cast(holder())); cp->symbol_at_put(_imcp_invoke_name, name); cp->symbol_at_put(_imcp_invoke_signature, signature); - cp->set_preresolution(); + cp->set_has_preresolution(); // decide on access bits: public or not? int flags_bits = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_FINAL); @@ -1954,6 +1962,22 @@ void Method::print_value_on(outputStream* st) const { if (WizardMode && code() != NULL) st->print(" ((nmethod*)%p)", code()); } +#if INCLUDE_SERVICES +// Size Statistics +void Method::collect_statistics(KlassSizeStats *sz) const { + int mysize = sz->count(this); + sz->_method_bytes += mysize; + sz->_method_all_bytes += mysize; + sz->_rw_bytes += mysize; + + if (constMethod()) { + constMethod()->collect_statistics(sz); + } + if (method_data()) { + method_data()->collect_statistics(sz); + } +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 72a4faf11d7..339380f6735 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,6 +101,7 @@ class LocalVariableTableElement; class AdapterHandlerEntry; class MethodData; class ConstMethod; +class KlassSizeStats; class Method : public Metadata { friend class VMStructs; @@ -127,8 +128,8 @@ class Method : public Metadata { InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations #ifdef TIERED - jlong _prev_time; // Previous time the rate was acquired float _rate; // Events (invocation and backedge counter increments) per millisecond + jlong _prev_time; // Previous time the rate was acquired #endif #ifndef PRODUCT @@ -593,6 +594,9 @@ class Method : public Metadata { static int header_size() { return sizeof(Method)/HeapWordSize; } static int size(bool is_native); int size() const { return method_size(); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } @@ -760,18 +764,18 @@ class Method : public Metadata { // whether it is not compilable for another reason like having a // breakpoint set in it. bool is_not_compilable(int comp_level = CompLevel_any) const; - void set_not_compilable(int comp_level = CompLevel_all, bool report = true); + void set_not_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL); void set_not_compilable_quietly(int comp_level = CompLevel_all) { set_not_compilable(comp_level, false); } bool is_not_osr_compilable(int comp_level = CompLevel_any) const; - void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true); + void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL); void set_not_osr_compilable_quietly(int comp_level = CompLevel_all) { set_not_osr_compilable(comp_level, false); } private: - void print_made_not_compilable(int comp_level, bool is_osr, bool report); + void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason); public: bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index 71d9649c268..c7a200f9e47 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -27,6 +27,7 @@ #include "interpreter/bytecode.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/heapInspection.hpp" #include "oops/methodData.hpp" #include "prims/jvmtiRedefineClasses.hpp" #include "runtime/compilationPolicy.hpp" @@ -859,6 +860,15 @@ void MethodData::print_data_on(outputStream* st) const { } #endif +#if INCLUDE_SERVICES +// Size Statistics +void MethodData::collect_statistics(KlassSizeStats *sz) const { + int n = sz->count(this); + sz->_method_data_bytes += n; + sz->_method_all_bytes += n; + sz->_rw_bytes += n; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 133278878ef..2f45870f3d2 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -32,6 +32,7 @@ #include "runtime/orderAccess.hpp" class BytecodeStream; +class KlassSizeStats; // The MethodData object collects counts and other profile information // during zeroth-tier (interpretive) and first-tier execution. @@ -1289,6 +1290,9 @@ public: // My size int size_in_bytes() const { return _size; } int size() const { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif int creation_mileage() const { return _creation_mileage; } void set_creation_mileage(int x) { _creation_mileage = x; } @@ -1465,7 +1469,7 @@ public: void inc_decompile_count() { _nof_decompiles += 1; if (decompile_count() > (uint)PerMethodRecompilationCutoff) { - method()->set_not_compilable(CompLevel_full_optimization); + method()->set_not_compilable(CompLevel_full_optimization, true, "decompile_count > PerMethodRecompilationCutoff"); } } diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index 434fb74abcf..f040206391e 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -43,7 +43,8 @@ #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/copy.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -54,7 +55,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, KlassHandle klass_handle, Symbol* name, TRAPS) { assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(), @@ -461,7 +462,7 @@ void ObjArrayKlass::oop_follow_contents(oop obj) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert(obj->is_array(), "obj must be array"); @@ -472,7 +473,7 @@ void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, objarray_follow_contents(cm, obj, 0); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define if_do_metadata_checked(closure, nv_suffix) \ /* Make sure the non-virtual and the virtual versions match. */ \ @@ -573,7 +574,7 @@ int ObjArrayKlass::oop_adjust_pointers(oop obj) { return size; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { assert(obj->is_objArray(), "obj must be obj array"); ObjArrayKlass_OOP_ITERATE( \ @@ -591,7 +592,7 @@ int ObjArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p)) return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // JVM support diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index 2234aa8314d..74aa4f8d76d 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -28,6 +28,7 @@ #include "classfile/classLoaderData.hpp" #include "memory/specialized_oop_closures.hpp" #include "oops/arrayKlass.hpp" +#include "utilities/macros.hpp" // ObjArrayKlass is the klass for objArrays @@ -111,11 +112,11 @@ class ObjArrayKlass : public ArrayKlass { // Parallel Scavenge and Parallel Old PARALLEL_GC_DECLS -#ifndef SERIALGC +#if INCLUDE_ALL_GCS inline void oop_follow_contents(ParCompactionManager* cm, oop obj, int index); template inline void objarray_follow_contents(ParCompactionManager* cm, oop obj, int index); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Iterators int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) { diff --git a/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp index 4a948d82eac..23e809a7e0f 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp @@ -27,10 +27,11 @@ #include "gc_implementation/shared/markSweep.inline.hpp" #include "oops/objArrayKlass.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psCompactionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" -#endif +#endif // INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(oop obj, int index) { if (UseCompressedOops) { @@ -63,7 +64,7 @@ void ObjArrayKlass::objarray_follow_contents(oop obj, int index) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj, int index) { if (UseCompressedOops) { @@ -96,6 +97,6 @@ void ObjArrayKlass::objarray_follow_contents(ParCompactionManager* cm, oop obj, cm->push_objarray(a, end_index); // Push the continuation. } } -#endif // #ifndef SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_OBJARRAYKLASS_INLINE_HPP diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index 7cb04ff4c00..94e68ed3263 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -29,6 +29,7 @@ #include "memory/memRegion.hpp" #include "memory/specialized_oop_closures.hpp" #include "oops/metadata.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" // oopDesc is the top baseclass for objects classes. The {name}Desc classes describe @@ -298,7 +299,7 @@ class oopDesc { // reference field in "this". void follow_contents(void); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Parallel Scavenge void push_contents(PSPromotionManager* pm); @@ -306,7 +307,7 @@ class oopDesc { void update_contents(ParCompactionManager* cm); void follow_contents(ParCompactionManager* cm); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS bool is_scavengable() const; @@ -316,13 +317,13 @@ class oopDesc { void forward_to(oop p); bool cas_forward_to(oop p, markOop compare); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Like "forward_to", but inserts the forwarding pointer atomically. // Exactly one thread succeeds in inserting the forwarding pointer, and // this call returns "NULL" for that thread; any other thread has the // value of the forwarding pointer returned and does not modify "this". oop forward_to_atomic(oop p); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS oop forwardee() const; @@ -334,10 +335,10 @@ class oopDesc { // return the size of this oop. This is used by the MarkSweep collector. int adjust_pointers(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Parallel old void update_header(ParCompactionManager* cm); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // mark-sweep support void follow_body(int begin, int end); @@ -354,7 +355,7 @@ class oopDesc { ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_iterate_backwards(OopClosureType* blk); diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index c097617478d..3c71e15f87c 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ #include "oops/oop.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "bytes_x86.hpp" #endif @@ -227,12 +228,12 @@ inline oop oopDesc::decode_heap_oop(oop v) { return v; } // might not be the same as oop. inline narrowOop oopDesc::encode_klass_not_null(Klass* v) { - assert(!is_null(v), "oop value can never be zero"); + assert(!is_null(v), "klass value can never be zero"); assert(check_klass_alignment(v), "Address not aligned"); address base = Universe::narrow_klass_base(); int shift = Universe::narrow_klass_shift(); uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); - assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); + assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding"); uint64_t result = pd >> shift; assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow"); assert(decode_klass(result) == v, "reversibility"); @@ -760,7 +761,7 @@ inline int oopDesc::oop_iterate_no_header(OopClosure* blk, MemRegion mr) { ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) { \ @@ -770,6 +771,6 @@ inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) { \ ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DEFN) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_OOP_INLINE_HPP diff --git a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp index 050678185f3..d8e40477f79 100644 --- a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp @@ -25,14 +25,15 @@ #ifndef SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP #define SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/parNewGeneration.hpp" #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" #include "gc_implementation/parallelScavenge/psCompactionManager.hpp" #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS inline void oopDesc::update_contents(ParCompactionManager* cm) { // The klass field must be updated before anything else diff --git a/hotspot/src/share/vm/oops/oop.psgc.inline.hpp b/hotspot/src/share/vm/oops/oop.psgc.inline.hpp index 4d8c3d63da0..ea184f36339 100644 --- a/hotspot/src/share/vm/oops/oop.psgc.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.psgc.inline.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_OOPS_OOP_PSGC_INLINE_HPP #define SHARE_VM_OOPS_OOP_PSGC_INLINE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS // ParallelScavengeHeap methods diff --git a/hotspot/src/share/vm/oops/symbol.cpp b/hotspot/src/share/vm/oops/symbol.cpp index f2253dbcce0..54601899287 100644 --- a/hotspot/src/share/vm/oops/symbol.cpp +++ b/hotspot/src/share/vm/oops/symbol.cpp @@ -152,6 +152,7 @@ char* Symbol::as_C_string_flexible_buffer(Thread* t, } void Symbol::print_symbol_on(outputStream* st) const { + ResourceMark rm; st = st ? st : tty; st->print("%s", as_quoted_ascii()); } diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp index 9b6ec260cda..56863a02469 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp @@ -39,6 +39,7 @@ #include "oops/typeArrayKlass.hpp" #include "oops/typeArrayOop.hpp" #include "runtime/handles.inline.hpp" +#include "utilities/macros.hpp" bool TypeArrayKlass::compute_is_subtype_of(Klass* k) { if (!k->oop_is_typeArray()) { @@ -208,13 +209,13 @@ void TypeArrayKlass::oop_follow_contents(oop obj) { // know that Universe::TypeArrayKlass never moves. } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void TypeArrayKlass::oop_follow_contents(ParCompactionManager* cm, 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. } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int TypeArrayKlass::oop_adjust_pointers(oop obj) { assert(obj->is_typeArray(),"must be a type array"); @@ -240,7 +241,7 @@ int TypeArrayKlass::oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegio return t->object_size(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void TypeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { ShouldNotReachHere(); assert(obj->is_typeArray(),"must be a type array"); @@ -251,7 +252,7 @@ TypeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { assert(obj->is_typeArray(),"must be a type array"); return typeArrayOop(obj)->object_size(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void TypeArrayKlass::initialize(TRAPS) { // Nothing to do. Having this function is handy since objArrayKlasses can be diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 5b80bd75c4b..3da308c27b2 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -420,14 +420,24 @@ const char* InlineTree::check_can_parse(ciMethod* callee) { } //------------------------------print_inlining--------------------------------- -// Really, the failure_msg can be a success message also. -void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const { - C->print_inlining(callee_method, inline_level(), caller_bci, failure_msg ? failure_msg : "inline"); - if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); - if (Verbose && callee_method) { - const InlineTree *top = this; - while( top->caller_tree() != NULL ) { top = top->caller_tree(); } - //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); +void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, + const char* msg, bool success) const { + assert(msg != NULL, "just checking"); + if (C->log() != NULL) { + if (success) { + C->log()->inline_success(msg); + } else { + C->log()->inline_fail(msg); + } + } + if (PrintInlining) { + C->print_inlining(callee_method, inline_level(), caller_bci, msg); + if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); + if (Verbose && callee_method) { + const InlineTree *top = this; + while( top->caller_tree() != NULL ) { top = top->caller_tree(); } + //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); + } } } @@ -451,23 +461,23 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, // Do some initial checks. if (!pass_initial_checks(caller_method, caller_bci, callee_method)) { - if (PrintInlining) print_inlining(callee_method, caller_bci, "failed initial checks"); + print_inlining(callee_method, caller_bci, "failed initial checks", + false /* !success */); return NULL; } // Do some parse checks. failure_msg = check_can_parse(callee_method); if (failure_msg != NULL) { - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, failure_msg, + false /* !success */); return NULL; } // Check if inlining policy says no. WarmCallInfo wci = *(initial_wci); - failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci, should_delay); - if (failure_msg != NULL && C->log() != NULL) { - C->log()->inline_fail(failure_msg); - } + failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, + &wci, should_delay); #ifndef PRODUCT if (UseOldInlining && InlineWarmCalls @@ -487,7 +497,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, wci = *(WarmCallInfo::always_hot()); else wci = *(WarmCallInfo::always_cold()); - } + } if (!InlineWarmCalls) { if (!wci.is_cold() && !wci.is_hot()) { // Do not inline the warm calls. @@ -496,11 +506,10 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, } if (!wci.is_cold()) { - // In -UseOldInlining, the failure_msg may also be a success message. - if (failure_msg == NULL) failure_msg = "inline (hot)"; - // Inline! - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, + failure_msg ? failure_msg : "inline (hot)", + true /* success */); if (UseOldInlining) build_inline_tree_for_callee(callee_method, jvms, caller_bci); if (InlineWarmCalls && !wci.is_hot()) @@ -509,8 +518,9 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, } // Do not inline - if (failure_msg == NULL) failure_msg = "too cold to inline"; - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, + failure_msg ? failure_msg : "too cold to inline", + false /* !success */ ); return NULL; } diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index fa481caae22..e1891226189 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -516,6 +516,9 @@ develop(bool, SpecialArraysEquals, true, \ "special version of Arrays.equals(char[],char[])") \ \ + product(bool, SpecialEncodeISOArray, true, \ + "special version of ISO_8859_1$Encoder.encodeISOArray") \ + \ develop(bool, BailoutToInterpreterForThrows, false, \ "Compiled methods which throws/catches exceptions will be " \ "deopt and intp.") \ diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 89a7c46f6ed..8cac8ee769b 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -305,11 +305,13 @@ class LateInlineCallGenerator : public DirectCallGenerator { void LateInlineCallGenerator::do_late_inline() { // Can't inline it if (call_node() == NULL || call_node()->outcnt() == 0 || - call_node()->in(0) == NULL || call_node()->in(0)->is_top()) + call_node()->in(0) == NULL || call_node()->in(0)->is_top()) { return; + } + const TypeTuple *r = call_node()->tf()->domain(); for (int i1 = 0; i1 < method()->arg_size(); i1++) { - if (call_node()->in(TypeFunc::Parms + i1)->is_top()) { + if (call_node()->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) { assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); return; } diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index e8c23b38e33..c90b76d4adb 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -165,13 +165,13 @@ uint ReturnNode::match_edge(uint idx) const { #ifndef PRODUCT -void ReturnNode::dump_req() const { +void ReturnNode::dump_req(outputStream *st) const { // Dump the required inputs, enclosed in '(' and ')' uint i; // Exit value of loop - for( i=0; iprint("returns"); - if( in(i) ) tty->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); - else tty->print("_ "); + for (i = 0; i < req(); i++) { // For all required inputs + if (i == TypeFunc::Parms) st->print("returns"); + if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); + else st->print("_ "); } } #endif @@ -208,13 +208,13 @@ uint RethrowNode::match_edge(uint idx) const { } #ifndef PRODUCT -void RethrowNode::dump_req() const { +void RethrowNode::dump_req(outputStream *st) const { // Dump the required inputs, enclosed in '(' and ')' uint i; // Exit value of loop - for( i=0; iprint("exception"); - if( in(i) ) tty->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); - else tty->print("_ "); + for (i = 0; i < req(); i++) { // For all required inputs + if (i == TypeFunc::Parms) st->print("exception"); + if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); + else st->print("_ "); } } #endif @@ -330,7 +330,8 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c st->print(" %s%d]=#ScObj" INT32_FORMAT, msg, i, sco_n); return; } - if( OptoReg::is_valid(regalloc->get_reg_first(n))) { // Check for undefined + if (regalloc->node_regs_max_index() > 0 && + OptoReg::is_valid(regalloc->get_reg_first(n))) { // Check for undefined char buf[50]; regalloc->dump_register(n,buf); st->print(" %s%d]=%s",msg,i,buf); @@ -381,7 +382,7 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c //------------------------------format----------------------------------------- void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const { st->print(" #"); - if( _method ) { + if (_method) { _method->print_short_name(st); st->print(" @ bci:%d ",_bci); } else { @@ -393,21 +394,22 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) MachSafePointNode *mcall = n->as_MachSafePoint(); uint i; // Print locals - for( i = 0; i < (uint)loc_size(); i++ ) - format_helper( regalloc, st, mcall->local(this, i), "L[", i, &scobjs ); + for (i = 0; i < (uint)loc_size(); i++) + format_helper(regalloc, st, mcall->local(this, i), "L[", i, &scobjs); // Print stack for (i = 0; i < (uint)stk_size(); i++) { if ((uint)(_stkoff + i) >= mcall->len()) st->print(" oob "); else - format_helper( regalloc, st, mcall->stack(this, i), "STK[", i, &scobjs ); + format_helper(regalloc, st, mcall->stack(this, i), "STK[", i, &scobjs); } for (i = 0; (int)i < nof_monitors(); i++) { Node *box = mcall->monitor_box(this, i); Node *obj = mcall->monitor_obj(this, i); - if ( OptoReg::is_valid(regalloc->get_reg_first(box)) ) { + if (regalloc->node_regs_max_index() > 0 && + OptoReg::is_valid(regalloc->get_reg_first(box))) { box = BoxLockNode::box_node(box); - format_helper( regalloc, st, box, "MON-BOX[", i, &scobjs ); + format_helper(regalloc, st, box, "MON-BOX[", i, &scobjs); } else { OptoReg::Name box_reg = BoxLockNode::reg(box); st->print(" MON-BOX%d=%s+%d", @@ -420,7 +422,7 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) if (BoxLockNode::box_node(box)->is_eliminated()) obj_msg = "MON-OBJ(LOCK ELIMINATED)["; } - format_helper( regalloc, st, obj, obj_msg, i, &scobjs ); + format_helper(regalloc, st, obj, obj_msg, i, &scobjs); } for (i = 0; i < (uint)scobjs.length(); i++) { @@ -463,9 +465,9 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) st->print(" ["); cifield = iklass->nonstatic_field_at(0); cifield->print_name_on(st); - format_helper( regalloc, st, fld_node, ":", 0, &scobjs ); + format_helper(regalloc, st, fld_node, ":", 0, &scobjs); } else { - format_helper( regalloc, st, fld_node, "[", 0, &scobjs ); + format_helper(regalloc, st, fld_node, "[", 0, &scobjs); } for (uint j = 1; j < nf; j++) { fld_node = mcall->in(first_ind+j); @@ -473,9 +475,9 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) st->print(", ["); cifield = iklass->nonstatic_field_at(j); cifield->print_name_on(st); - format_helper( regalloc, st, fld_node, ":", j, &scobjs ); + format_helper(regalloc, st, fld_node, ":", j, &scobjs); } else { - format_helper( regalloc, st, fld_node, ", [", j, &scobjs ); + format_helper(regalloc, st, fld_node, ", [", j, &scobjs); } } } @@ -483,7 +485,7 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) } } st->print_cr(""); - if (caller() != NULL) caller()->format(regalloc, n, st); + if (caller() != NULL) caller()->format(regalloc, n, st); } @@ -586,15 +588,15 @@ JVMState* JVMState::clone_deep(Compile* C) const { uint CallNode::cmp( const Node &n ) const { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } #ifndef PRODUCT -void CallNode::dump_req() const { +void CallNode::dump_req(outputStream *st) const { // Dump the required inputs, enclosed in '(' and ')' uint i; // Exit value of loop - for( i=0; iprint("("); - if( in(i) ) tty->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); - else tty->print("_ "); + for (i = 0; i < req(); i++) { // For all required inputs + if (i == TypeFunc::Parms) st->print("("); + if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); + else st->print("_ "); } - tty->print(")"); + st->print(")"); } void CallNode::dump_spec(outputStream *st) const { diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index fee091f798d..0aa35c214e5 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -126,7 +126,7 @@ public: virtual uint ideal_reg() const { return NotAMachineReg; } virtual uint match_edge(uint idx) const; #ifndef PRODUCT - virtual void dump_req() const; + virtual void dump_req(outputStream *st = tty) const; #endif }; @@ -147,7 +147,7 @@ class RethrowNode : public Node { virtual uint match_edge(uint idx) const; virtual uint ideal_reg() const { return NotAMachineReg; } #ifndef PRODUCT - virtual void dump_req() const; + virtual void dump_req(outputStream *st = tty) const; #endif }; @@ -579,7 +579,7 @@ public: virtual uint match_edge(uint idx) const; #ifndef PRODUCT - virtual void dump_req() const; + virtual void dump_req(outputStream *st = tty) const; virtual void dump_spec(outputStream *st) const; #endif }; diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index 3f726991dd0..f97b385f422 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -127,6 +127,7 @@ macro(DivL) macro(DivMod) macro(DivModI) macro(DivModL) +macro(EncodeISOArray) macro(EncodeP) macro(EncodePKlass) macro(ExpD) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index f090939186d..ae9d6996a9c 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -692,7 +692,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr PhaseGVN gvn(node_arena(), estimated_size); set_initial_gvn(&gvn); - if (PrintInlining) { + if (PrintInlining || PrintIntrinsics NOT_PRODUCT( || PrintOptoInlining)) { _print_inlining_list = new (comp_arena())GrowableArray(comp_arena(), 1, 1, PrintInliningBuffer()); } { // Scope for timing the parser @@ -2049,7 +2049,7 @@ void Compile::Optimize() { } // (End scope of igvn; run destructor if necessary for asserts.) - dump_inlining(); + dump_inlining(); // A method with only infinite loops has no edges entering loops from root { NOT_PRODUCT( TracePhase t2("graphReshape", &_t_graphReshaping, TimeCompiler); ) @@ -3497,7 +3497,7 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n } void Compile::dump_inlining() { - if (PrintInlining) { + if (PrintInlining || PrintIntrinsics NOT_PRODUCT( || PrintOptoInlining)) { // Print inlining message for candidates that we couldn't inline // for lack of space or non constant receiver for (int i = 0; i < _late_inlines.length(); i++) { diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index 5d094c99afc..9a7562d01fb 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -553,7 +553,13 @@ void Parse::do_call() { rtype = ctype; } } else { - assert(rtype == ctype, "mismatched return types"); // symbolic resolution enforces this + // Symbolic resolution enforces the types to be the same. + // NOTE: We must relax the assert for unloaded types because two + // different ciType instances of the same unloaded class type + // can appear to be "loaded" by different loaders (depending on + // the accessing class). + assert(!rtype->is_loaded() || !ctype->is_loaded() || rtype == ctype, + err_msg_res("mismatched return types: rtype=%s, ctype=%s", rtype->name(), ctype->name())); } // If the return type of the method is not loaded, assert that the diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index 659828e509f..c5a93dfa68f 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -523,7 +523,8 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de case Op_AryEq: case Op_StrComp: case Op_StrEquals: - case Op_StrIndexOf: { + case Op_StrIndexOf: + case Op_EncodeISOArray: { add_local_var(n, PointsToNode::ArgEscape); delayed_worklist->push(n); // Process it later. break; @@ -701,7 +702,8 @@ void ConnectionGraph::add_final_edges(Node *n) { case Op_AryEq: case Op_StrComp: case Op_StrEquals: - case Op_StrIndexOf: { + case Op_StrIndexOf: + case Op_EncodeISOArray: { // char[] arrays passed to string intrinsic do not escape but // they are not scalar replaceable. Adjust escape state for them. // Start from in(2) edge since in(1) is memory edge. @@ -2581,15 +2583,22 @@ Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArra } // Otherwise skip it (the call updated 'result' value). } else if (result->Opcode() == Op_SCMemProj) { - assert(result->in(0)->is_LoadStore(), "sanity"); - const Type *at = igvn->type(result->in(0)->in(MemNode::Address)); + Node* mem = result->in(0); + Node* adr = NULL; + if (mem->is_LoadStore()) { + adr = mem->in(MemNode::Address); + } else { + assert(mem->Opcode() == Op_EncodeISOArray, "sanity"); + adr = mem->in(3); // Memory edge corresponds to destination array + } + const Type *at = igvn->type(adr); if (at != Type::TOP) { assert (at->isa_ptr() != NULL, "pointer type required."); int idx = C->get_alias_index(at->is_ptr()); assert(idx != alias_idx, "Object is not scalar replaceable if a LoadStore node access its field"); break; } - result = result->in(0)->in(MemNode::Memory); + result = mem->in(MemNode::Memory); } } if (result->is_Phi()) { @@ -2927,6 +2936,11 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) if (m->is_MergeMem()) { assert(_mergemem_worklist.contains(m->as_MergeMem()), "EA: missing MergeMem node in the worklist"); } + } else if (use->Opcode() == Op_EncodeISOArray) { + if (use->in(MemNode::Memory) == n || use->in(3) == n) { + // EncodeISOArray overwrites destination array + memnode_worklist.append_if_missing(use); + } } else { uint op = use->Opcode(); if (!(op == Op_CmpP || op == Op_Conv2B || @@ -2962,6 +2976,16 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) n = n->as_MemBar()->proj_out(TypeFunc::Memory); if (n == NULL) continue; + } else if (n->Opcode() == Op_EncodeISOArray) { + // get the memory projection + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node *use = n->fast_out(i); + if (use->Opcode() == Op_SCMemProj) { + n = use; + break; + } + } + assert(n->Opcode() == Op_SCMemProj, "memory projection required"); } else { assert(n->is_Mem(), "memory node required."); Node *addr = n->in(MemNode::Address); @@ -2999,7 +3023,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) Node *use = n->fast_out(i); if (use->is_Phi() || use->is_ClearArray()) { memnode_worklist.append_if_missing(use); - } else if(use->is_Mem() && use->in(MemNode::Memory) == n) { + } else if (use->is_Mem() && use->in(MemNode::Memory) == n) { if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores continue; memnode_worklist.append_if_missing(use); @@ -3010,6 +3034,11 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) assert(use->in(MemNode::Memory) != n, "EA: missing memory path"); } else if (use->is_MergeMem()) { assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); + } else if (use->Opcode() == Op_EncodeISOArray) { + if (use->in(MemNode::Memory) == n || use->in(3) == n) { + // EncodeISOArray overwrites destination array + memnode_worklist.append_if_missing(use); + } } else { uint op = use->Opcode(); if (!(op == Op_StoreCM || diff --git a/hotspot/src/share/vm/opto/generateOptoStub.cpp b/hotspot/src/share/vm/opto/generateOptoStub.cpp index 56fc759f2d2..c5ebd5ad524 100644 --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp @@ -88,12 +88,12 @@ void GraphKit::gen_stub(address C_function, thread, in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::last_Java_pc_offset())); -#if defined(SPARC) || defined(IA64) +#if defined(SPARC) Node* adr_flags = basic_plus_adr(top(), thread, in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::flags_offset())); -#endif /* defined(SPARC) || defined(IA64) */ +#endif /* defined(SPARC) */ // Drop in the last_Java_sp. last_Java_fp is not touched. @@ -102,10 +102,8 @@ void GraphKit::gen_stub(address C_function, // users will look at the other fields. // Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset())); -#ifndef IA64 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS); store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias); -#endif // Set _thread_in_native // The order of stores into TLS is critical! Setting _thread_in_native MUST @@ -210,19 +208,12 @@ void GraphKit::gen_stub(address C_function, //----------------------------- // Clear last_Java_sp -#ifdef IA64 - if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); -#endif - store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias); -#ifdef IA64 - if (os::is_MP() && UseMembar) insert_mem_bar(new MemBarVolatileNode()); -#endif // def IA64 // Clear last_Java_pc and (optionally)_flags store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias); -#if defined(SPARC) || defined(IA64) +#if defined(SPARC) store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); -#endif /* defined(SPARC) || defined(IA64) */ +#endif /* defined(SPARC) */ #ifdef IA64 Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp index 0928704d9cb..1f811b8f4b8 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -547,7 +547,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { // max. 2 chars allowed if (value >= -9 && value <= 99) { - sprintf(buffer, INT64_FORMAT, value); + sprintf(buffer, JLONG_FORMAT, value); print_prop(short_name, buffer); } else { print_prop(short_name, "L"); diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 5ca4bae13d7..35006ff23b4 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -175,6 +175,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe case Op_StrEquals: case Op_StrIndexOf: case Op_AryEq: + case Op_EncodeISOArray: // Not a legit memory op for implicit null check regardless of // embedded loads continue; diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 313339edfde..e3aee707e4a 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -290,6 +290,7 @@ class LibraryCallKit : public GraphKit { bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id); Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting); Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); + bool inline_encodeISOArray(); }; @@ -381,6 +382,10 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { // These also use the arraycopy intrinsic mechanism: if (!InlineArrayCopy) return NULL; break; + case vmIntrinsics::_encodeISOArray: + if (!SpecialEncodeISOArray) return NULL; + if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return NULL; + break; case vmIntrinsics::_checkIndex: // We do not intrinsify this. The optimizer does fine with it. return NULL; @@ -799,6 +804,9 @@ bool LibraryCallKit::try_to_inline() { case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: return inline_cipherBlockChaining_AESCrypt(intrinsic_id()); + case vmIntrinsics::_encodeISOArray: + return inline_encodeISOArray(); + default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmSymbols.hpp without implementing it here. @@ -3559,7 +3567,6 @@ bool LibraryCallKit::inline_native_getLength() { // public static T[] java.util.Arrays.copyOf( U[] original, int newLength, Class newType); // public static T[] java.util.Arrays.copyOfRange(U[] original, int from, int to, Class newType); bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { - return false; if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; // Get the arguments. @@ -5369,6 +5376,47 @@ LibraryCallKit::generate_unchecked_arraycopy(const TypePtr* adr_type, src_start, dest_start, copy_length XTOP); } +//-------------inline_encodeISOArray----------------------------------- +// encode char[] to byte[] in ISO_8859_1 +bool LibraryCallKit::inline_encodeISOArray() { + assert(callee()->signature()->size() == 5, "encodeISOArray has 5 parameters"); + // no receiver since it is static method + Node *src = argument(0); + Node *src_offset = argument(1); + Node *dst = argument(2); + Node *dst_offset = argument(3); + Node *length = argument(4); + + const Type* src_type = src->Value(&_gvn); + const Type* dst_type = dst->Value(&_gvn); + const TypeAryPtr* top_src = src_type->isa_aryptr(); + const TypeAryPtr* top_dest = dst_type->isa_aryptr(); + if (top_src == NULL || top_src->klass() == NULL || + top_dest == NULL || top_dest->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(); + BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (src_elem != T_CHAR || dst_elem != T_BYTE) { + return false; + } + Node* src_start = array_element_address(src, src_offset, src_elem); + Node* dst_start = array_element_address(dst, dst_offset, dst_elem); + // 'src_start' points to src array + scaled offset + // 'dst_start' points to dst array + scaled offset + + const TypeAryPtr* mtype = TypeAryPtr::BYTES; + Node* enc = new (C) EncodeISOArrayNode(control(), memory(mtype), src_start, dst_start, length); + enc = _gvn.transform(enc); + Node* res_mem = _gvn.transform(new (C) SCMemProjNode(enc)); + set_memory(res_mem, mtype); + set_result(enc); + return true; +} + //----------------------------inline_reference_get---------------------------- // public T java.lang.ref.Reference.get(); bool LibraryCallKit::inline_reference_get() { diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 259e10a56df..b405bbcf6ba 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -613,6 +613,7 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const { case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_EncodeISOArray: case Op_AryEq: { return false; } @@ -717,6 +718,7 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const { case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_EncodeISOArray: case Op_AryEq: { // Do not unroll a loop with String intrinsics code. // String intrinsics are large and have loops. diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index 30970102d5f..b9b014e050b 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -506,7 +506,7 @@ int MachConstantNode::constant_offset() { #ifndef PRODUCT void MachNullCheckNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { int reg = ra_->get_reg_first(in(1)->in(_vidx)); - tty->print("%s %s", Name(), Matcher::regName[reg]); + st->print("%s %s", Name(), Matcher::regName[reg]); } #endif diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 2c45140816e..2dde491380c 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -361,14 +361,21 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me } // Otherwise skip it (the call updated 'mem' value). } else if (mem->Opcode() == Op_SCMemProj) { - assert(mem->in(0)->is_LoadStore(), "sanity"); - const TypePtr* atype = mem->in(0)->in(MemNode::Address)->bottom_type()->is_ptr(); + mem = mem->in(0); + Node* adr = NULL; + if (mem->is_LoadStore()) { + adr = mem->in(MemNode::Address); + } else { + assert(mem->Opcode() == Op_EncodeISOArray, "sanity"); + adr = mem->in(3); // Destination array + } + const TypePtr* atype = adr->bottom_type()->is_ptr(); int adr_idx = Compile::current()->get_alias_index(atype); if (adr_idx == alias_idx) { assert(false, "Object is not scalar replaceable if a LoadStore node access its field"); return NULL; } - mem = mem->in(0)->in(MemNode::Memory); + mem = mem->in(MemNode::Memory); } else { return mem; } @@ -445,7 +452,7 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type * } values.at_put(j, val); } else if (val->Opcode() == Op_SCMemProj) { - assert(val->in(0)->is_LoadStore(), "sanity"); + assert(val->in(0)->is_LoadStore() || val->in(0)->Opcode() == Op_EncodeISOArray, "sanity"); assert(false, "Object is not scalar replaceable if a LoadStore node access its field"); return NULL; } else { diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 0c6f5ea8ec2..ffd3cc28346 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -919,6 +919,7 @@ static void match_alias_type(Compile* C, Node* n, Node* m) { case Op_AryEq: case Op_MemBarVolatile: case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type? + case Op_EncodeISOArray: nidx = Compile::AliasIdxTop; nat = NULL; break; @@ -1982,6 +1983,7 @@ void Matcher::find_shared( Node *n ) { case Op_StrEquals: case Op_StrIndexOf: case Op_AryEq: + case Op_EncodeISOArray: set_shared(n); // Force result into register (it will be anyways) break; case Op_ConP: { // Convert pointers above the centerline to NUL @@ -2183,6 +2185,13 @@ void Matcher::find_shared( Node *n ) { n->del_req(4); break; } + case Op_EncodeISOArray: { + // Restructure into a binary tree for Matching. + Node* pair = new (C) BinaryNode(n->in(3), n->in(4)); + n->set_req(3, pair); + n->del_req(4); + break; + } default: break; } diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index bea81f210da..35fc4b7fc7f 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -2796,6 +2796,26 @@ const Type *StrIntrinsicNode::Value( PhaseTransform *phase ) const { return bottom_type(); } +//============================================================================= +//------------------------------match_edge------------------------------------- +// Do not match memory edge +uint EncodeISOArrayNode::match_edge(uint idx) const { + return idx == 2 || idx == 3; // EncodeISOArray src (Binary dst len) +} + +//------------------------------Ideal------------------------------------------ +// Return a node which is more "ideal" than the current node. Strip out +// control copies +Node *EncodeISOArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { + return remove_dead_region(phase, can_reshape) ? this : NULL; +} + +//------------------------------Value------------------------------------------ +const Type *EncodeISOArrayNode::Value(PhaseTransform *phase) const { + if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP; + return bottom_type(); +} + //============================================================================= MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent) : MultiNode(TypeFunc::Parms + (precedent == NULL? 0: 1)), diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 92a3d12feba..640eacb116a 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -888,6 +888,22 @@ public: virtual const Type* bottom_type() const { return TypeInt::BOOL; } }; + +//------------------------------EncodeISOArray-------------------------------- +// encode char[] to byte[] in ISO_8859_1 +class EncodeISOArrayNode: public Node { +public: + EncodeISOArrayNode(Node *control, Node* arymem, Node* s1, Node* s2, Node* c): Node(control, arymem, s1, s2, c) {}; + virtual int Opcode() const; + virtual bool depends_only_on_test() const { return false; } + virtual const Type* bottom_type() const { return TypeInt::INT; } + virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } + virtual uint match_edge(uint idx) const; + virtual uint ideal_reg() const { return Op_RegI; } + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual const Type *Value(PhaseTransform *phase) const; +}; + //------------------------------MemBar----------------------------------------- // There are different flavors of Memory Barriers to match the Java Memory // Model. Monitor-enter and volatile-load act as Aquires: no following ref diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index 9983c84d8e2..16157f68bd7 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -1476,35 +1476,35 @@ static bool is_disconnected(const Node* n) { } #ifdef ASSERT -static void dump_orig(Node* orig) { +static void dump_orig(Node* orig, outputStream *st) { Compile* C = Compile::current(); - if (NotANode(orig)) orig = NULL; - if (orig != NULL && !C->node_arena()->contains(orig)) orig = NULL; - if (orig == NULL) return; - tty->print(" !orig="); + if (NotANode(orig)) orig = NULL; + if (orig != NULL && !C->node_arena()->contains(orig)) orig = NULL; + if (orig == NULL) return; + st->print(" !orig="); Node* fast = orig->debug_orig(); // tortoise & hare algorithm to detect loops - if (NotANode(fast)) fast = NULL; + if (NotANode(fast)) fast = NULL; while (orig != NULL) { bool discon = is_disconnected(orig); // if discon, print [123] else 123 - if (discon) tty->print("["); + if (discon) st->print("["); if (!Compile::current()->node_arena()->contains(orig)) - tty->print("o"); - tty->print("%d", orig->_idx); - if (discon) tty->print("]"); + st->print("o"); + st->print("%d", orig->_idx); + if (discon) st->print("]"); orig = orig->debug_orig(); - if (NotANode(orig)) orig = NULL; - if (orig != NULL && !C->node_arena()->contains(orig)) orig = NULL; - if (orig != NULL) tty->print(","); + if (NotANode(orig)) orig = NULL; + if (orig != NULL && !C->node_arena()->contains(orig)) orig = NULL; + if (orig != NULL) st->print(","); if (fast != NULL) { // Step fast twice for each single step of orig: fast = fast->debug_orig(); - if (NotANode(fast)) fast = NULL; + if (NotANode(fast)) fast = NULL; if (fast != NULL && fast != orig) { fast = fast->debug_orig(); - if (NotANode(fast)) fast = NULL; + if (NotANode(fast)) fast = NULL; } if (fast == orig) { - tty->print("..."); + st->print("..."); break; } } @@ -1531,35 +1531,34 @@ void Node::set_debug_orig(Node* orig) { //------------------------------dump------------------------------------------ // Dump a Node -void Node::dump() const { +void Node::dump(const char* suffix, outputStream *st) const { Compile* C = Compile::current(); bool is_new = C->node_arena()->contains(this); _in_dump_cnt++; - tty->print("%c%d\t%s\t=== ", - is_new ? ' ' : 'o', _idx, Name()); + st->print("%c%d\t%s\t=== ", is_new ? ' ' : 'o', _idx, Name()); // Dump the required and precedence inputs - dump_req(); - dump_prec(); + dump_req(st); + dump_prec(st); // Dump the outputs - dump_out(); + dump_out(st); if (is_disconnected(this)) { #ifdef ASSERT - tty->print(" [%d]",debug_idx()); - dump_orig(debug_orig()); + st->print(" [%d]",debug_idx()); + dump_orig(debug_orig(), st); #endif - tty->cr(); + st->cr(); _in_dump_cnt--; return; // don't process dead nodes } // Dump node-specific info - dump_spec(tty); + dump_spec(st); #ifdef ASSERT // Dump the non-reset _debug_idx - if( Verbose && WizardMode ) { - tty->print(" [%d]",debug_idx()); + if (Verbose && WizardMode) { + st->print(" [%d]",debug_idx()); } #endif @@ -1569,88 +1568,88 @@ void Node::dump() const { const TypeInstPtr *toop = t->isa_instptr(); const TypeKlassPtr *tkls = t->isa_klassptr(); ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL ); - if( klass && klass->is_loaded() && klass->is_interface() ) { - tty->print(" Interface:"); - } else if( toop ) { - tty->print(" Oop:"); - } else if( tkls ) { - tty->print(" Klass:"); + if (klass && klass->is_loaded() && klass->is_interface()) { + st->print(" Interface:"); + } else if (toop) { + st->print(" Oop:"); + } else if (tkls) { + st->print(" Klass:"); } - t->dump(); - } else if( t == Type::MEMORY ) { - tty->print(" Memory:"); - MemNode::dump_adr_type(this, adr_type(), tty); - } else if( Verbose || WizardMode ) { - tty->print(" Type:"); - if( t ) { - t->dump(); + t->dump_on(st); + } else if (t == Type::MEMORY) { + st->print(" Memory:"); + MemNode::dump_adr_type(this, adr_type(), st); + } else if (Verbose || WizardMode) { + st->print(" Type:"); + if (t) { + t->dump_on(st); } else { - tty->print("no type"); + st->print("no type"); } } else if (t->isa_vect() && this->is_MachSpillCopy()) { // Dump MachSpillcopy vector type. - t->dump(); + t->dump_on(st); } if (is_new) { - debug_only(dump_orig(debug_orig())); + debug_only(dump_orig(debug_orig(), st)); Node_Notes* nn = C->node_notes_at(_idx); if (nn != NULL && !nn->is_clear()) { if (nn->jvms() != NULL) { - tty->print(" !jvms:"); - nn->jvms()->dump_spec(tty); + st->print(" !jvms:"); + nn->jvms()->dump_spec(st); } } } - tty->cr(); + if (suffix) st->print(suffix); _in_dump_cnt--; } //------------------------------dump_req-------------------------------------- -void Node::dump_req() const { +void Node::dump_req(outputStream *st) const { // Dump the required input edges for (uint i = 0; i < req(); i++) { // For all required inputs Node* d = in(i); if (d == NULL) { - tty->print("_ "); + st->print("_ "); } else if (NotANode(d)) { - tty->print("NotANode "); // uninitialized, sentinel, garbage, etc. + st->print("NotANode "); // uninitialized, sentinel, garbage, etc. } else { - tty->print("%c%d ", Compile::current()->node_arena()->contains(d) ? ' ' : 'o', d->_idx); + st->print("%c%d ", Compile::current()->node_arena()->contains(d) ? ' ' : 'o', d->_idx); } } } //------------------------------dump_prec------------------------------------- -void Node::dump_prec() const { +void Node::dump_prec(outputStream *st) const { // Dump the precedence edges int any_prec = 0; for (uint i = req(); i < len(); i++) { // For all precedence inputs Node* p = in(i); if (p != NULL) { - if( !any_prec++ ) tty->print(" |"); - if (NotANode(p)) { tty->print("NotANode "); continue; } - tty->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); + if (!any_prec++) st->print(" |"); + if (NotANode(p)) { st->print("NotANode "); continue; } + st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); } } } //------------------------------dump_out-------------------------------------- -void Node::dump_out() const { +void Node::dump_out(outputStream *st) const { // Delimit the output edges - tty->print(" [["); + st->print(" [["); // Dump the output edges for (uint i = 0; i < _outcnt; i++) { // For all outputs Node* u = _out[i]; if (u == NULL) { - tty->print("_ "); + st->print("_ "); } else if (NotANode(u)) { - tty->print("NotANode "); + st->print("NotANode "); } else { - tty->print("%c%d ", Compile::current()->node_arena()->contains(u) ? ' ' : 'o', u->_idx); + st->print("%c%d ", Compile::current()->node_arena()->contains(u) ? ' ' : 'o', u->_idx); } } - tty->print("]] "); + st->print("]] "); } //------------------------------dump_nodes------------------------------------- diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index f0c1df3a8b0..0dafb00182f 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -994,12 +994,13 @@ public: #ifndef PRODUCT Node* find(int idx) const; // Search the graph for the given idx. Node* find_ctrl(int idx) const; // Search control ancestors for the given idx. - void dump() const; // Print this node, + void dump() const { dump("\n"); } // Print this node. + void dump(const char* suffix, outputStream *st = tty) const;// Print this node. void dump(int depth) const; // Print this node, recursively to depth d void dump_ctrl(int depth) const; // Print control nodes, to depth d - virtual void dump_req() const; // Print required-edge info - virtual void dump_prec() const; // Print precedence-edge info - virtual void dump_out() const; // Print the output edge info + virtual void dump_req(outputStream *st = tty) const; // Print required-edge info + virtual void dump_prec(outputStream *st = tty) const; // Print precedence-edge info + virtual void dump_out(outputStream *st = tty) const; // Print the output edge info virtual void dump_spec(outputStream *st) const {}; // Print per-node info void verify_edges(Unique_Node_List &visited); // Verify bi-directional edges void verify() const; // Check Def-Use info for my subgraph diff --git a/hotspot/src/share/vm/opto/optoreg.hpp b/hotspot/src/share/vm/opto/optoreg.hpp index e6427ea459a..a21311b9c6d 100644 --- a/hotspot/src/share/vm/opto/optoreg.hpp +++ b/hotspot/src/share/vm/opto/optoreg.hpp @@ -77,7 +77,7 @@ class OptoReg VALUE_OBJ_CLASS_SPEC { // (We would like to have an operator+ for RegName, but it is not // a class, so this would be illegal in C++.) - static void dump( int ); + static void dump(int, outputStream *st = tty); // Get the stack slot number of an OptoReg::Name static unsigned int reg2stack( OptoReg::Name r) { diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index c880832a446..2cf487f8ad6 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -73,7 +73,8 @@ protected: const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay); const char* should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const; const char* should_not_inline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const; - void print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const; + void print_inlining(ciMethod* callee_method, int caller_bci, + const char* msg, bool success) const; InlineTree *caller_tree() const { return _caller_tree; } InlineTree* callee_at(int bci, ciMethod* m) const; diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index ac6f4ec8f76..9de92a2ae54 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -487,7 +487,8 @@ void Parse::do_multianewarray() { fun, NULL, TypeRawPtr::BOTTOM, makecon(TypeKlassPtr::make(array_klass)), length[0], length[1], length[2], - length[3], length[4]); + (ndimensions > 2) ? length[3] : NULL, + (ndimensions > 3) ? length[4] : NULL); } else { // Create a java array for dimension sizes Node* dims = NULL; diff --git a/hotspot/src/share/vm/opto/regalloc.cpp b/hotspot/src/share/vm/opto/regalloc.cpp index 79dde4066c1..7ac02165662 100644 --- a/hotspot/src/share/vm/opto/regalloc.cpp +++ b/hotspot/src/share/vm/opto/regalloc.cpp @@ -40,6 +40,7 @@ PhaseRegAlloc::PhaseRegAlloc( uint unique, PhaseCFG &cfg, Phase(Register_Allocation), _cfg(cfg), _matcher(matcher), _node_oops(Thread::current()->resource_area()), _node_regs(0), + _node_regs_max_index(0), _framesize(0xdeadbeef) { int i; diff --git a/hotspot/src/share/vm/opto/regmask.cpp b/hotspot/src/share/vm/opto/regmask.cpp index 59413388ca7..f286a873471 100644 --- a/hotspot/src/share/vm/opto/regmask.cpp +++ b/hotspot/src/share/vm/opto/regmask.cpp @@ -108,13 +108,13 @@ int find_hihghest_bit( uint32 mask ) { //------------------------------dump------------------------------------------- #ifndef PRODUCT -void OptoReg::dump( int r ) { - switch( r ) { - case Special: tty->print("r---"); break; - case Bad: tty->print("rBAD"); break; +void OptoReg::dump(int r, outputStream *st) { + switch (r) { + case Special: st->print("r---"); break; + case Bad: st->print("rBAD"); break; default: - if( r < _last_Mach_Reg ) tty->print(Matcher::regName[r]); - else tty->print("rS%d",r); + if (r < _last_Mach_Reg) st->print(Matcher::regName[r]); + else st->print("rS%d",r); break; } } @@ -404,53 +404,53 @@ uint RegMask::Size() const { #ifndef PRODUCT //------------------------------print------------------------------------------ -void RegMask::dump( ) const { - tty->print("["); +void RegMask::dump(outputStream *st) const { + st->print("["); RegMask rm = *this; // Structure copy into local temp OptoReg::Name start = rm.find_first_elem(); // Get a register - if( OptoReg::is_valid(start) ) { // Check for empty mask + if (OptoReg::is_valid(start)) { // Check for empty mask rm.Remove(start); // Yank from mask - OptoReg::dump(start); // Print register + OptoReg::dump(start, st); // Print register OptoReg::Name last = start; // Now I have printed an initial register. // Print adjacent registers as "rX-rZ" instead of "rX,rY,rZ". // Begin looping over the remaining registers. - while( 1 ) { // + while (1) { // OptoReg::Name reg = rm.find_first_elem(); // Get a register - if( !OptoReg::is_valid(reg) ) + if (!OptoReg::is_valid(reg)) break; // Empty mask, end loop rm.Remove(reg); // Yank from mask - if( last+1 == reg ) { // See if they are adjacent + if (last+1 == reg) { // See if they are adjacent // Adjacent registers just collect into long runs, no printing. last = reg; } else { // Ending some kind of run - if( start == last ) { // 1-register run; no special printing - } else if( start+1 == last ) { - tty->print(","); // 2-register run; print as "rX,rY" - OptoReg::dump(last); + if (start == last) { // 1-register run; no special printing + } else if (start+1 == last) { + st->print(","); // 2-register run; print as "rX,rY" + OptoReg::dump(last, st); } else { // Multi-register run; print as "rX-rZ" - tty->print("-"); - OptoReg::dump(last); + st->print("-"); + OptoReg::dump(last, st); } - tty->print(","); // Seperate start of new run + st->print(","); // Seperate start of new run start = last = reg; // Start a new register run - OptoReg::dump(start); // Print register + OptoReg::dump(start, st); // Print register } // End of if ending a register run or not } // End of while regmask not empty - if( start == last ) { // 1-register run; no special printing - } else if( start+1 == last ) { - tty->print(","); // 2-register run; print as "rX,rY" - OptoReg::dump(last); + if (start == last) { // 1-register run; no special printing + } else if (start+1 == last) { + st->print(","); // 2-register run; print as "rX,rY" + OptoReg::dump(last, st); } else { // Multi-register run; print as "rX-rZ" - tty->print("-"); - OptoReg::dump(last); + st->print("-"); + OptoReg::dump(last, st); } - if( rm.is_AllStack() ) tty->print("..."); + if (rm.is_AllStack()) st->print("..."); } - tty->print("]"); + st->print("]"); } #endif diff --git a/hotspot/src/share/vm/opto/regmask.hpp b/hotspot/src/share/vm/opto/regmask.hpp index e4c31dcefb2..7e3376b38a3 100644 --- a/hotspot/src/share/vm/opto/regmask.hpp +++ b/hotspot/src/share/vm/opto/regmask.hpp @@ -310,7 +310,7 @@ public: #ifndef PRODUCT void print() const { dump(); } - void dump() const; // Print a mask + void dump(outputStream *st = tty) const; // Print a mask #endif static const RegMask Empty; // Common empty mask diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 1a8ee2597dd..3928c23aff3 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1542,10 +1542,10 @@ bool TypeLong::is_finite() const { static const char* longnamenear(jlong x, const char* xname, char* buf, jlong n) { if (n > x) { if (n >= x + 10000) return NULL; - sprintf(buf, "%s+" INT64_FORMAT, xname, n - x); + sprintf(buf, "%s+" JLONG_FORMAT, xname, n - x); } else if (n < x) { if (n <= x - 10000) return NULL; - sprintf(buf, "%s-" INT64_FORMAT, xname, x - n); + sprintf(buf, "%s-" JLONG_FORMAT, xname, x - n); } else { return xname; } @@ -1557,11 +1557,11 @@ static const char* longname(char* buf, jlong n) { if (n == min_jlong) return "min"; else if (n < min_jlong + 10000) - sprintf(buf, "min+" INT64_FORMAT, n - min_jlong); + sprintf(buf, "min+" JLONG_FORMAT, n - min_jlong); else if (n == max_jlong) return "max"; else if (n > max_jlong - 10000) - sprintf(buf, "max-" INT64_FORMAT, max_jlong - n); + sprintf(buf, "max-" JLONG_FORMAT, max_jlong - n); else if ((str = longnamenear(max_juint, "maxuint", buf, n)) != NULL) return str; else if ((str = longnamenear(max_jint, "maxint", buf, n)) != NULL) @@ -1569,7 +1569,7 @@ static const char* longname(char* buf, jlong n) { else if ((str = longnamenear(min_jint, "minint", buf, n)) != NULL) return str; else - sprintf(buf, INT64_FORMAT, n); + sprintf(buf, JLONG_FORMAT, n); return buf; } diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp index 1bbc5599b75..118fe9c1bde 100644 --- a/hotspot/src/share/vm/precompiled/precompiled.hpp +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp @@ -24,6 +24,7 @@ // Precompiled headers are turned off for Sun Studion, // or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles. + #ifndef DONT_USE_PRECOMPILED_HEADER # include "asm/assembler.hpp" @@ -285,7 +286,7 @@ # include "c1/c1_ValueType.hpp" # include "c1/c1_globals.hpp" #endif // COMPILER1 -#ifndef SERIALGC +#if INCLUDE_ALL_GCS # include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp" # include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" # include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" @@ -314,6 +315,6 @@ # include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp" # include "gc_implementation/shared/gcPolicyCounters.hpp" # include "gc_implementation/shared/parGCAllocBuffer.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // !DONT_USE_PRECOMPILED_HEADER diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index ddbde753f1c..f45568a7ca7 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -32,9 +32,10 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "memory/gcLocker.inline.hpp" @@ -2641,7 +2642,7 @@ JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); } jobject ret = JNIHandles::make_local(env, o->obj_field(offset)); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If G1 is enabled and we are accessing the value of the referent // field in a reference object then we need to register a non-null // referent with the SATB barrier. @@ -2660,7 +2661,7 @@ JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret); #else /* USDT2 */ diff --git a/hotspot/src/share/vm/prims/jniCheck.hpp b/hotspot/src/share/vm/prims/jniCheck.hpp index e5f5071b3a3..169ab7be3f4 100644 --- a/hotspot/src/share/vm/prims/jniCheck.hpp +++ b/hotspot/src/share/vm/prims/jniCheck.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ #ifndef SHARE_VM_PRIMS_JNICHECK_HPP #define SHARE_VM_PRIMS_JNICHECK_HPP -#ifndef KERNEL #include "runtime/thread.hpp" -#endif extern "C" { // Report a JNI failure caught by -Xcheck:jni. Perform a core dump. diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index f899aac02e7..84ab5f04828 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -484,15 +484,6 @@ JVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver)) JVM_END -JVM_ENTRY(void, JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable)) - JVMWrapper("JVM_PrintStackTrace"); - // Note: This is no longer used in Merlin, but we still support it for compatibility. - oop exception = JNIHandles::resolve_non_null(receiver); - oop stream = JNIHandles::resolve_non_null(printable); - java_lang_Throwable::print_stack_trace(exception, stream); -JVM_END - - JVM_ENTRY(jint, JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)) JVMWrapper("JVM_GetStackTraceDepth"); oop exception = JNIHandles::resolve(throwable); @@ -1582,13 +1573,22 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls)) if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); if (k->oop_is_instance()) { - typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->type_annotations()->class_annotations(), CHECK_NULL); - return (jbyteArray) JNIHandles::make_local(env, a); + Annotations* type_annotations = InstanceKlass::cast(k)->type_annotations(); + if (type_annotations != NULL) { + typeArrayOop a = Annotations::make_java_array(type_annotations->class_annotations(), CHECK_NULL); + return (jbyteArray) JNIHandles::make_local(env, a); + } } } return NULL; JVM_END +static void bounds_check(constantPoolHandle cp, jint index, TRAPS) { + if (!cp->is_within_bounds(index)) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool index out of bounds"); + } +} + JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method)) { JVMWrapper("JVM_GetMethodParameters"); @@ -1598,15 +1598,31 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method)) Handle reflected_method (THREAD, JNIHandles::resolve_non_null(method)); const int num_params = mh->method_parameters_length(); - if(0 != num_params) { + if (0 != num_params) { + // make sure all the symbols are properly formatted + for (int i = 0; i < num_params; i++) { + MethodParametersElement* params = mh->method_parameters_start(); + int index = params[i].name_cp_index; + bounds_check(mh->constants(), index, CHECK_NULL); + + if (0 != index && !mh->constants()->tag_at(index).is_utf8()) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + "Wrong type at constant pool index"); + } + + } + objArrayOop result_oop = oopFactory::new_objArray(SystemDictionary::reflect_Parameter_klass(), num_params, CHECK_NULL); objArrayHandle result (THREAD, result_oop); - for(int i = 0; i < num_params; i++) { + for (int i = 0; i < num_params; i++) { MethodParametersElement* params = mh->method_parameters_start(); - Symbol* const sym = mh->constants()->symbol_at(params[i].name_cp_index); + // For a 0 index, give a NULL symbol + Symbol* const sym = 0 != params[i].name_cp_index ? + mh->constants()->symbol_at(params[i].name_cp_index) : NULL; + int flags = params[i].flags; oop param = Reflection::new_parameter(reflected_method, i, sym, - params[i].flags, CHECK_NULL); + flags, CHECK_NULL); result->obj_at_put(i, param); } return (jobjectArray)JNIHandles::make_local(env, result()); @@ -1830,13 +1846,6 @@ JVM_ENTRY(jint, JVM_ConstantPoolGetSize(JNIEnv *env, jobject obj, jobject unused JVM_END -static void bounds_check(constantPoolHandle cp, jint index, TRAPS) { - if (!cp->is_within_bounds(index)) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool index out of bounds"); - } -} - - JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject obj, jobject unused, jint index)) { JVMWrapper("JVM_ConstantPoolGetClassAt"); @@ -1851,7 +1860,6 @@ JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject obj, jobject u } JVM_END - JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject obj, jobject unused, jint index)) { JVMWrapper("JVM_ConstantPoolGetClassAtIfLoaded"); @@ -2294,6 +2302,15 @@ JVM_QUICK_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int metho JVM_END +JVM_QUICK_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index)) + JVMWrapper("JVM_IsVMGeneratedMethodIx"); + ResourceMark rm(THREAD); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); + k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); + Method* method = InstanceKlass::cast(k)->methods()->at(method_index); + return method->is_overpass(); +JVM_END + JVM_ENTRY(const char*, JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)) JVMWrapper("JVM_GetMethodIxIxUTF"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); @@ -4511,10 +4528,6 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i // consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat // counter defined in runtimeService.cpp. info->is_attachable = AttachListener::is_attach_supported(); -#ifdef KERNEL - info->is_kernel_jvm = 1; // true; -#else // KERNEL info->is_kernel_jvm = 0; // false; -#endif // KERNEL } JVM_END diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index 899138ede9e..dea46d126eb 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -212,9 +212,6 @@ JVM_IsNaN(jdouble d); JNIEXPORT void JNICALL JVM_FillInStackTrace(JNIEnv *env, jobject throwable); -JNIEXPORT void JNICALL -JVM_PrintStackTrace(JNIEnv *env, jobject throwable, jobject printable); - JNIEXPORT jint JNICALL JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable); @@ -862,6 +859,13 @@ JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index); JNIEXPORT jboolean JNICALL JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index); +/* + * Is the given method generated by the VM. + * The method is identified by method_index. + */ +JNIEXPORT jboolean JNICALL +JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index); + /* * Returns the name of a given method in UTF format. * The result remains valid until JVM_ReleaseUTF is called. diff --git a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp index 92adaaf80e8..00da7ca6ca1 100644 --- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp +++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ #ifndef SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP #define SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP -#ifndef JVMTI_KERNEL #include "jvmtifiles/jvmti.h" -#endif // forward declaration class JvmtiEnv; diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index cb3b3db1e1c..318fe4e0b7e 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -647,8 +647,6 @@ JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) { return JVMTI_ERROR_NONE; } /* end GetJLocationFormat */ -#ifndef JVMTI_KERNEL - // // Thread functions // @@ -3436,5 +3434,3 @@ JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) { } return err; } /* end SetSystemProperty */ - -#endif // !JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index eed31268141..56387634179 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,10 +74,8 @@ JvmtiEnvBase::globally_initialize() { JvmtiManageCapabilities::initialize(); -#ifndef JVMTI_KERNEL // register extension functions and events JvmtiExtensions::register_extensions(); -#endif // !JVMTI_KERNEL #ifdef JVMTI_TRACE JvmtiTrace::initialize(); @@ -236,14 +234,12 @@ JvmtiEnvBase::env_dispose() { // Same situation as with events (see above) set_native_method_prefixes(0, NULL); -#ifndef JVMTI_KERNEL JvmtiTagMap* tag_map_to_deallocate = _tag_map; set_tag_map(NULL); // A tag map can be big, deallocate it now if (tag_map_to_deallocate != NULL) { delete tag_map_to_deallocate; } -#endif // !JVMTI_KERNEL _needs_clean_up = true; } @@ -255,14 +251,12 @@ JvmtiEnvBase::~JvmtiEnvBase() { // There is a small window of time during which the tag map of a // disposed environment could have been reallocated. // Make sure it is gone. -#ifndef JVMTI_KERNEL JvmtiTagMap* tag_map_to_deallocate = _tag_map; set_tag_map(NULL); // A tag map can be big, deallocate it now if (tag_map_to_deallocate != NULL) { delete tag_map_to_deallocate; } -#endif // !JVMTI_KERNEL _magic = BAD_MAGIC; } @@ -593,8 +587,6 @@ JvmtiEnvBase::get_jni_class_non_null(Klass* k) { return (jclass)jni_reference(k->java_mirror()); } -#ifndef JVMTI_KERNEL - // // Field Information // @@ -1482,5 +1474,3 @@ JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) { } } } - -#endif // !JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp index d7b7d7cf63c..929dcf22260 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp @@ -35,6 +35,7 @@ #include "runtime/thread.hpp" #include "runtime/vm_operations.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" // // Forward Declarations diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index cb5a1f454d9..ab66dca33d6 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,10 @@ #include "runtime/vframe.hpp" #include "services/attachListener.hpp" #include "services/serviceUtil.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psMarkSweep.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef JVMTI_TRACE #define EVT_TRACE(evt,out) if ((JvmtiTrace::event_trace_flags(evt) & JvmtiTrace::SHOW_EVENT_SENT) != 0) { SafeResourceMark rm; tty->print_cr out; } @@ -677,7 +678,6 @@ void JvmtiExport::report_unsupported(bool on) { } -#ifndef JVMTI_KERNEL static inline Klass* oop_to_klass(oop obj) { Klass* k = obj->klass(); @@ -2178,7 +2178,6 @@ extern "C" { typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *); } -#ifndef SERVICES_KERNEL jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { char ebuf[1024]; char buffer[JVM_MAXPATHLEN]; @@ -2259,7 +2258,6 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { } return result; } -#endif // SERVICES_KERNEL //////////////////////////////////////////////////////////////////////////////////////////////// @@ -2457,4 +2455,3 @@ JvmtiGCMarker::~JvmtiGCMarker() { JvmtiExport::post_garbage_collection_finish(); } } -#endif // JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp index 1100d526995..a1e0e0bd44a 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp @@ -34,6 +34,7 @@ #include "runtime/handles.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" // Must be included after jvmti.h. #include "code/jvmticmlr.h" diff --git a/hotspot/src/share/vm/prims/jvmtiExtensions.hpp b/hotspot/src/share/vm/prims/jvmtiExtensions.hpp index a5e3433315e..f85003f6bf6 100644 --- a/hotspot/src/share/vm/prims/jvmtiExtensions.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExtensions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,9 @@ #ifndef SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP #define SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP -#ifndef JVMTI_KERNEL #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/allocation.hpp" -#endif // JvmtiExtensions // diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.cpp b/hotspot/src/share/vm/prims/jvmtiImpl.cpp index bb7714d4932..4a1747e1bd2 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -905,8 +905,6 @@ void JvmtiSuspendControl::print() { #endif } -#ifndef KERNEL - JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event( nmethod* nm) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); @@ -1098,5 +1096,3 @@ void JvmtiDeferredEventQueue::process_pending_events() { } } } - -#endif // ndef KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.hpp b/hotspot/src/share/vm/prims/jvmtiImpl.hpp index d785930be0d..204bd83f124 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.hpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -25,8 +25,6 @@ #ifndef SHARE_VM_PRIMS_JVMTIIMPL_HPP #define SHARE_VM_PRIMS_JVMTIIMPL_HPP -#ifndef JVMTI_KERNEL - #include "classfile/systemDictionary.hpp" #include "jvmtifiles/jvmti.h" #include "oops/objArrayOop.hpp" @@ -435,7 +433,6 @@ public: static void print(); }; -#endif // !JVMTI_KERNEL /** * When a thread (such as the compiler thread or VM thread) cannot post a diff --git a/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp b/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp index e5b25fa3a82..8c182f318ec 100644 --- a/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -25,10 +25,8 @@ #ifndef SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP #define SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP -#ifndef JVMTI_KERNEL #include "runtime/objectMonitor.hpp" #include "utilities/growableArray.hpp" -#endif // // class JvmtiRawMonitor diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index a9d3d5f1e39..ce1ec56ef65 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/verifier.hpp" #include "code/codeCache.hpp" @@ -115,43 +116,6 @@ bool VM_RedefineClasses::doit_prologue() { return true; } -// Keep track of marked on-stack metadata so it can be cleared. -GrowableArray* _marked_objects = NULL; -NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) - -// Walk metadata on the stack and mark it so that redefinition doesn't delete -// it. Class unloading also walks the previous versions and might try to -// delete it, so this class is used by class unloading also. -MetadataOnStackMark::MetadataOnStackMark() { - assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); - NOT_PRODUCT(_is_active = true;) - if (_marked_objects == NULL) { - _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray(1000, true); - } - Threads::metadata_do(Metadata::mark_on_stack); - CodeCache::alive_nmethods_do(nmethod::mark_on_stack); - CompileBroker::mark_on_stack(); -} - -MetadataOnStackMark::~MetadataOnStackMark() { - assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); - // Unmark everything that was marked. Can't do the same walk because - // redefine classes messes up the code cache so the set of methods - // might not be the same. - for (int i = 0; i< _marked_objects->length(); i++) { - _marked_objects->at(i)->set_on_stack(false); - } - _marked_objects->clear(); // reuse growable array for next time. - NOT_PRODUCT(_is_active = false;) -} - -// Record which objects are marked so we can unmark the same objects. -void MetadataOnStackMark::record(Metadata* m) { - assert(_is_active, "metadata on stack marking is active"); - _marked_objects->push(m); -} - - void VM_RedefineClasses::doit() { Thread *thread = Thread::current(); @@ -314,76 +278,23 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, case JVM_CONSTANT_NameAndType: { int name_ref_i = scratch_cp->name_ref_index_at(scratch_i); - int new_name_ref_i = 0; - bool match = (name_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(name_ref_i, *merge_cp_p, name_ref_i, - THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(name_ref_i, *merge_cp_p, - THREAD); - if (found_i != 0) { - guarantee(found_i != name_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_name_ref_i = found_i; - map_index(scratch_cp, name_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, name_ref_i, merge_cp_p, merge_cp_length_p, - THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. - new_name_ref_i = *merge_cp_length_p - 1; - } - } + int new_name_ref_i = find_or_append_indirect_entry(scratch_cp, name_ref_i, merge_cp_p, + merge_cp_length_p, THREAD); int signature_ref_i = scratch_cp->signature_ref_index_at(scratch_i); - int new_signature_ref_i = 0; - match = (signature_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(signature_ref_i, *merge_cp_p, - signature_ref_i, THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(signature_ref_i, - *merge_cp_p, THREAD); - if (found_i != 0) { - guarantee(found_i != signature_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_signature_ref_i = found_i; - map_index(scratch_cp, signature_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, signature_ref_i, merge_cp_p, - merge_cp_length_p, THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. - new_signature_ref_i = *merge_cp_length_p - 1; - } - } + int new_signature_ref_i = find_or_append_indirect_entry(scratch_cp, signature_ref_i, + merge_cp_p, merge_cp_length_p, + THREAD); // If the referenced entries already exist in *merge_cp_p, then // both new_name_ref_i and new_signature_ref_i will both be 0. // In that case, all we are appending is the current entry. - if (new_name_ref_i == 0) { - new_name_ref_i = name_ref_i; - } else { + if (new_name_ref_i != name_ref_i) { RC_TRACE(0x00080000, ("NameAndType entry@%d name_ref_index change: %d to %d", *merge_cp_length_p, name_ref_i, new_name_ref_i)); } - if (new_signature_ref_i == 0) { - new_signature_ref_i = signature_ref_i; - } else { + if (new_signature_ref_i != signature_ref_i) { RC_TRACE(0x00080000, ("NameAndType entry@%d signature_ref_index change: %d to %d", *merge_cp_length_p, signature_ref_i, new_signature_ref_i)); @@ -405,76 +316,12 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, case JVM_CONSTANT_Methodref: { int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i); - int new_klass_ref_i = 0; - bool match = (klass_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(klass_ref_i, *merge_cp_p, klass_ref_i, - THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match + int new_klass_ref_i = find_or_append_indirect_entry(scratch_cp, klass_ref_i, + merge_cp_p, merge_cp_length_p, THREAD); - int found_i = scratch_cp->find_matching_entry(klass_ref_i, *merge_cp_p, - THREAD); - if (found_i != 0) { - guarantee(found_i != klass_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_klass_ref_i = found_i; - map_index(scratch_cp, klass_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, klass_ref_i, merge_cp_p, merge_cp_length_p, - THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. Without the optimization where we - // use JVM_CONSTANT_UnresolvedClass, then up to two entries - // could be appended. - new_klass_ref_i = *merge_cp_length_p - 1; - } - } - - int name_and_type_ref_i = - scratch_cp->uncached_name_and_type_ref_index_at(scratch_i); - int new_name_and_type_ref_i = 0; - match = (name_and_type_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(name_and_type_ref_i, *merge_cp_p, - name_and_type_ref_i, THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(name_and_type_ref_i, - *merge_cp_p, THREAD); - if (found_i != 0) { - guarantee(found_i != name_and_type_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_name_and_type_ref_i = found_i; - map_index(scratch_cp, name_and_type_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, name_and_type_ref_i, merge_cp_p, - merge_cp_length_p, THREAD); - // The above call to append_entry() can append more than - // one entry so the post call query of *merge_cp_length_p - // is required in order to get the right index for the - // JVM_CONSTANT_NameAndType entry. - new_name_and_type_ref_i = *merge_cp_length_p - 1; - } - } - - // If the referenced entries already exist in *merge_cp_p, then - // both new_klass_ref_i and new_name_and_type_ref_i will both be - // 0. In that case, all we are appending is the current entry. - if (new_klass_ref_i == 0) { - new_klass_ref_i = klass_ref_i; - } - if (new_name_and_type_ref_i == 0) { - new_name_and_type_ref_i = name_and_type_ref_i; - } + int name_and_type_ref_i = scratch_cp->uncached_name_and_type_ref_index_at(scratch_i); + int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i, + merge_cp_p, merge_cp_length_p, THREAD); const char *entry_name; switch (scratch_cp->tag_at(scratch_i).value()) { @@ -517,6 +364,72 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, (*merge_cp_length_p)++; } break; + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_MethodType: + { + int ref_i = scratch_cp->method_type_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("MethodType entry@%d ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + (*merge_cp_p)->method_type_index_at_put(*merge_cp_length_p, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_MethodHandle: + { + int ref_kind = scratch_cp->method_handle_ref_kind_at(scratch_i); + int ref_i = scratch_cp->method_handle_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("MethodHandle entry@%d ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + (*merge_cp_p)->method_handle_index_at_put(*merge_cp_length_p, ref_kind, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_InvokeDynamic: + { + // TBD: cross-checks and possible extra appends into CP and bsm operands + // are needed as well. This issue is tracked by a separate bug 8007037. + int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); + + int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + + (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + // At this stage, Class or UnresolvedClass could be here, but not // ClassIndex case JVM_CONSTANT_ClassIndex: // fall through @@ -543,6 +456,35 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, } // end append_entry() +int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp, + int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { + + int new_ref_i = ref_i; + bool match = (ref_i < *merge_cp_length_p) && + scratch_cp->compare_entry_to(ref_i, *merge_cp_p, ref_i, THREAD); + + if (!match) { + // forward reference in *merge_cp_p or not a direct match + int found_i = scratch_cp->find_matching_entry(ref_i, *merge_cp_p, THREAD); + if (found_i != 0) { + guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree"); + // Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry. + new_ref_i = found_i; + map_index(scratch_cp, ref_i, found_i); + } else { + // no match found so we have to append this entry to *merge_cp_p + append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p, THREAD); + // The above call to append_entry() can only append one entry + // so the post call query of *merge_cp_length_p is only for + // the sake of consistency. + new_ref_i = *merge_cp_length_p - 1; + } + } + + return new_ref_i; +} // end find_or_append_indirect_entry() + + void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS) { AnnotationArray* save; @@ -1158,6 +1100,8 @@ bool VM_RedefineClasses::merge_constant_pools(constantPoolHandle old_cp, } } // end for each old_cp entry + ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0); + // We don't need to sanity check that *merge_cp_length_p is within // *merge_cp_p bounds since we have the minimum on-entry check above. (*merge_cp_length_p) = old_i; @@ -1334,27 +1278,19 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( return JVMTI_ERROR_INTERNAL; } - int orig_length = old_cp->orig_length(); - if (orig_length == 0) { - // This old_cp is an actual original constant pool. We save - // the original length in the merged constant pool so that - // merge_constant_pools() can be more efficient. If a constant - // pool has a non-zero orig_length() value, then that constant - // pool was created by a merge operation in RedefineClasses. - merge_cp->set_orig_length(old_cp->length()); - } else { - // This old_cp is a merged constant pool from a previous - // RedefineClasses() calls so just copy the orig_length() - // value. - merge_cp->set_orig_length(old_cp->orig_length()); - } + // Update the version number of the constant pool + merge_cp->increment_and_save_version(old_cp->version()); ResourceMark rm(THREAD); _index_map_count = 0; _index_map_p = new intArray(scratch_cp->length(), -1); + // reference to the cp holder is needed for copy_operands() + merge_cp->set_pool_holder(scratch_class()); bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp, &merge_cp_length, THREAD); + merge_cp->set_pool_holder(NULL); + if (!result) { // The merge can fail due to memory allocation failure or due // to robustness checks. @@ -1606,6 +1542,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, case Bytecodes::_getfield : // fall through case Bytecodes::_getstatic : // fall through case Bytecodes::_instanceof : // fall through + case Bytecodes::_invokedynamic : // fall through case Bytecodes::_invokeinterface: // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through @@ -2417,23 +2354,25 @@ void VM_RedefineClasses::set_new_constant_pool( int scratch_cp_length, TRAPS) { assert(scratch_cp->length() >= scratch_cp_length, "sanity check"); - // scratch_cp is a merged constant pool and has enough space for a - // worst case merge situation. We want to associate the minimum - // sized constant pool with the klass to save space. - constantPoolHandle smaller_cp(THREAD, - ConstantPool::allocate(loader_data, scratch_cp_length, - THREAD)); - // preserve orig_length() value in the smaller copy - int orig_length = scratch_cp->orig_length(); - assert(orig_length != 0, "sanity check"); - smaller_cp->set_orig_length(orig_length); - scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); - scratch_cp = smaller_cp; + // scratch_cp is a merged constant pool and has enough space for a + // worst case merge situation. We want to associate the minimum + // sized constant pool with the klass to save space. + constantPoolHandle smaller_cp(THREAD, + ConstantPool::allocate(loader_data, scratch_cp_length, THREAD)); - // attach new constant pool to klass - scratch_cp->set_pool_holder(scratch_class()); + // preserve version() value in the smaller copy + int version = scratch_cp->version(); + assert(version != 0, "sanity check"); + smaller_cp->set_version(version); // attach klass to new constant pool + // reference to the cp holder is needed for copy_operands() + smaller_cp->set_pool_holder(scratch_class()); + + scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); + scratch_cp = smaller_cp; + + // attach new constant pool to klass scratch_class->set_constants(scratch_cp()); int i; // for portability @@ -3151,11 +3090,9 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, Klass* the_class_oop = java_lang_Class::as_Klass(the_class_mirror); instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop); -#ifndef JVMTI_KERNEL // Remove all breakpoints in methods of this class JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); jvmti_breakpoints.clearall_in_class_at_safepoint(the_class_oop); -#endif // !JVMTI_KERNEL if (the_class_oop == Universe::reflect_invoke_cache()->klass()) { // We are redefining java.lang.reflect.Method. Method.invoke() is diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp index 7164413c8fa..d348ed2c759 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -421,10 +421,11 @@ class VM_RedefineClasses: public VM_Operation { // and in all direct and indirect subclasses. void increment_class_counter(InstanceKlass *ik, TRAPS); - // Support for constant pool merging (these routines are in alpha - // order): + // Support for constant pool merging (these routines are in alpha order): void append_entry(constantPoolHandle scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); + int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i, + constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); int find_new_index(int old_index); bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1, constantPoolHandle cp2, int index2); @@ -487,17 +488,4 @@ class VM_RedefineClasses: public VM_Operation { // and redefine implementation static bool is_modifiable_class(oop klass_mirror); }; - - -// Helper class to mark and unmark metadata used on the stack as either handles -// or executing methods, so that it can't be deleted during class redefinition -// and class unloading. -class MetadataOnStackMark : public StackObj { - NOT_PRODUCT(static bool _is_active;) - public: - MetadataOnStackMark() NOT_JVMTI_RETURN; - ~MetadataOnStackMark() NOT_JVMTI_RETURN; - static void record(Metadata* m) NOT_JVMTI_RETURN; -}; - #endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES_HPP diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index 3dbc70adf62..5d72029d264 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -45,9 +45,10 @@ #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "services/serviceUtil.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // JvmtiTagHashmapEntry // diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp index 6435f6251c7..89e3947807d 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,12 @@ #ifndef SHARE_VM_PRIMS_JVMTITAGMAP_HPP #define SHARE_VM_PRIMS_JVMTITAGMAP_HPP -#ifndef JVMTI_KERNEL #include "gc_interface/collectedHeap.hpp" #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/allocation.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/universe.hpp" -#endif // forward references class JvmtiTagHashmap; diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index 5fdd070aaa4..6162ae85032 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -40,6 +40,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" #endif diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index e56277b65d7..18252c15453 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -24,9 +24,10 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/allocation.inline.hpp" #include "prims/jni.h" #include "prims/jvm.h" @@ -189,7 +190,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject o if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); GET_OOP_FIELD(obj, offset, v) jobject ret = JNIHandles::make_local(env, v); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference // object. If G1 is enabled then we need to register a non-null // referent with the SATB barrier. @@ -212,7 +213,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject o G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return ret; UNSAFE_END @@ -247,7 +248,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, UnsafeWrapper("Unsafe_GetObject"); GET_OOP_FIELD(obj, offset, v) jobject ret = JNIHandles::make_local(env, v); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference // object. If G1 is enabled then we need to register non-null // referent with the SATB barrier. @@ -270,7 +271,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return ret; UNSAFE_END diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 6c60be19f10..7bbec834e70 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -36,12 +36,17 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS + +#ifdef INCLUDE_NMT +#include "services/memTracker.hpp" +#endif // INCLUDE_NMT bool WhiteBox::_used = false; @@ -85,7 +90,7 @@ WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name)) return closure.found(); WB_END -#ifndef SERIALGC +#if INCLUDE_ALL_GCS WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj)) G1CollectedHeap* g1 = G1CollectedHeap::heap(); oop result = JNIHandles::resolve(obj); @@ -108,7 +113,61 @@ WB_END WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o)) return (jint)HeapRegion::GrainBytes; WB_END -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS + +#ifdef INCLUDE_NMT +// Keep track of the 3 allocations in NMTAllocTest so we can free them later +// on and verify that they're not visible anymore +static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL; + +// Alloc memory using the test memory type so that we can use that to see if +// NMT picks it up correctly +WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env)) + void *mem; + + if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { + return false; + } + + // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track + // everything correctly. Total should be 512k held alive. + nmtMtTest1 = os::malloc(128 * 1024, mtTest); + mem = os::malloc(1024 * 1024, mtTest); + nmtMtTest2 = os::malloc(256 * 1024, mtTest); + os::free(mem, mtTest); + nmtMtTest3 = os::malloc(128 * 1024, mtTest); + + return true; +WB_END + +// Free the memory allocated by NMTAllocTest +WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env)) + + if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) { + return false; + } + + os::free(nmtMtTest1, mtTest); + nmtMtTest1 = NULL; + os::free(nmtMtTest2, mtTest); + nmtMtTest2 = NULL; + os::free(nmtMtTest3, mtTest); + nmtMtTest3 = NULL; + + return true; +WB_END + +// Block until the current generation of NMT data to be merged, used to reliably test the NMT feature +WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env)) + + if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { + return false; + } + + return MemTracker::wbtest_wait_for_data_merge(); +WB_END + +#endif // INCLUDE_NMT //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, @@ -171,12 +230,17 @@ static JNINativeMethod methods[] = { CC "(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", (void*) &WB_ParseCommandLine }, -#ifndef SERIALGC +#if INCLUDE_ALL_GCS {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous }, {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions }, {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize }, -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS +#ifdef INCLUDE_NMT + {CC"NMTAllocTest", CC"()Z", (void*)&WB_NMTAllocTest }, + {CC"NMTFreeTestMemory", CC"()Z", (void*)&WB_NMTFreeTestMemory }, + {CC"NMTWaitForDataMerge",CC"()Z", (void*)&WB_NMTWaitForDataMerge}, +#endif // INCLUDE_NMT }; #undef CC diff --git a/hotspot/src/share/vm/runtime/aprofiler.cpp b/hotspot/src/share/vm/runtime/aprofiler.cpp index 6c4e9cc428d..e71bfb587ef 100644 --- a/hotspot/src/share/vm/runtime/aprofiler.cpp +++ b/hotspot/src/share/vm/runtime/aprofiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,7 +129,7 @@ void AllocationProfiler::print(size_t cutoff) { assert(!is_active(), "AllocationProfiler cannot be active while printing profile"); tty->cr(); - tty->print_cr("Allocation profile (sizes in bytes, cutoff = %ld bytes):", cutoff * BytesPerWord); + tty->print_cr("Allocation profile (sizes in bytes, cutoff = " SIZE_FORMAT " bytes):", cutoff * BytesPerWord); tty->cr(); // Print regular instance klasses and basic type array klasses diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 5978382e9fe..de596c1a8ba 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ #include "services/management.hpp" #include "services/memTracker.hpp" #include "utilities/defaultStream.hpp" +#include "utilities/macros.hpp" #include "utilities/taskqueue.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" @@ -51,9 +52,9 @@ #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Note: This is a special bug reporting site for the JVM #define DEFAULT_VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/crash.jsp" @@ -532,7 +533,7 @@ char* SysClassPath::add_jars_to_path(char* path, const char* directory) { // Parses a memory size specification string. static bool atomull(const char *s, julong* result) { julong n = 0; - int args_read = sscanf(s, os::julong_format_specifier(), &n); + int args_read = sscanf(s, JULONG_FORMAT, &n); if (args_read != 1) { return false; } @@ -827,7 +828,8 @@ bool Arguments::process_argument(const char* arg, return true; } - const char * const argname = *arg == '+' || *arg == '-' ? arg + 1 : arg; + bool has_plus_minus = (*arg == '+' || *arg == '-'); + const char* const argname = has_plus_minus ? arg + 1 : arg; if (is_newly_obsolete(arg, &since)) { char version[256]; since.to_string(version, sizeof(version)); @@ -838,13 +840,29 @@ bool Arguments::process_argument(const char* arg, // For locked flags, report a custom error message if available. // Otherwise, report the standard unrecognized VM option. - Flag* locked_flag = Flag::find_flag((char*)argname, strlen(argname), true); - if (locked_flag != NULL) { + size_t arg_len; + const char* equal_sign = strchr(argname, '='); + if (equal_sign == NULL) { + arg_len = strlen(argname); + } else { + arg_len = equal_sign - argname; + } + + Flag* found_flag = Flag::find_flag((char*)argname, arg_len, true); + if (found_flag != NULL) { char locked_message_buf[BUFLEN]; - locked_flag->get_locked_message(locked_message_buf, BUFLEN); + found_flag->get_locked_message(locked_message_buf, BUFLEN); if (strlen(locked_message_buf) == 0) { - jio_fprintf(defaultStream::error_stream(), - "Unrecognized VM option '%s'\n", argname); + if (found_flag->is_bool() && !has_plus_minus) { + jio_fprintf(defaultStream::error_stream(), + "Missing +/- setting for VM option '%s'\n", argname); + } else if (!found_flag->is_bool() && has_plus_minus) { + jio_fprintf(defaultStream::error_stream(), + "Unexpected +/- setting in VM option '%s'\n", argname); + } else { + jio_fprintf(defaultStream::error_stream(), + "Improperly specified VM option '%s'\n", argname); + } } else { jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf); } @@ -1072,7 +1090,7 @@ void Arguments::set_tiered_flags() { } } -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS static void disable_adaptive_size_policy(const char* collector_name) { if (UseAdaptiveSizePolicy) { if (FLAG_IS_CMDLINE(UseAdaptiveSizePolicy)) { @@ -1284,7 +1302,7 @@ void Arguments::set_cms_and_parnew_gc_flags() { tty->print_cr("ConcGCThreads: %u", ConcGCThreads); } } -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS void set_object_alignment() { // Object alignment. @@ -1301,10 +1319,10 @@ void set_object_alignment() { // Oop encoding heap max OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes; -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS // Set CMS global values CompactibleFreeListSpace::set_cms_values(); -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS } bool verify_object_alignment() { @@ -1429,13 +1447,18 @@ void Arguments::set_ergonomics_flags() { } // Set the ClassMetaspaceSize to something that will not need to be // expanded, since it cannot be expanded. - if (UseCompressedKlassPointers && FLAG_IS_DEFAULT(ClassMetaspaceSize)) { - // 100,000 classes seems like a good size, so 100M assumes around 1K - // per klass. The vtable and oopMap is embedded so we don't have a fixed - // size per klass. Eventually, this will be parameterized because it - // would also be useful to determine the optimal size of the - // systemDictionary. - FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M); + if (UseCompressedKlassPointers) { + if (ClassMetaspaceSize > KlassEncodingMetaspaceMax) { + warning("Class metaspace size is too large for UseCompressedKlassPointers"); + FLAG_SET_DEFAULT(UseCompressedKlassPointers, false); + } else if (FLAG_IS_DEFAULT(ClassMetaspaceSize)) { + // 100,000 classes seems like a good size, so 100M assumes around 1K + // per klass. The vtable and oopMap is embedded so we don't have a fixed + // size per klass. Eventually, this will be parameterized because it + // would also be useful to determine the optimal size of the + // systemDictionary. + FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M); + } } } // Also checks that certain machines are slower with compressed oops @@ -1976,7 +1999,7 @@ bool Arguments::check_vm_args_consistency() { status = status && verify_min_value(ParGCArrayScanChunk, 1, "ParGCArrayScanChunk"); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { status = status && verify_percentage(InitiatingHeapOccupancyPercent, "InitiatingHeapOccupancyPercent"); @@ -1985,7 +2008,7 @@ bool Arguments::check_vm_args_consistency() { status = status && verify_min_value((intx)G1ConcMarkStepDurationMillis, 1, "G1ConcMarkStepDurationMillis"); } -#endif +#endif // INCLUDE_ALL_GCS status = status && verify_interval(RefDiscoveryPolicy, ReferenceProcessor::DiscoveryPolicyMin, @@ -2472,10 +2495,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // -Xshare:dump } else if (match_option(option, "-Xshare:dump", &tail)) { -#if defined(KERNEL) - vm_exit_during_initialization( - "Dumping a shared archive is not supported on the Kernel JVM.", NULL); -#elif !INCLUDE_CDS +#if !INCLUDE_CDS vm_exit_during_initialization( "Dumping a shared archive is not supported in this VM.", NULL); #else @@ -3157,7 +3177,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { UNSUPPORTED_OPTION(UseLargePages, "-XX:+UseLargePages"); #endif -#if !INCLUDE_ALTERNATE_GCS +#if !INCLUDE_ALL_GCS if (UseParallelGC) { warning("Parallel GC is not supported in this VM. Using Serial GC."); } @@ -3170,7 +3190,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { if (UseParNewGC) { warning("Par New GC is not supported in this VM. Using Serial GC."); } -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS #ifndef PRODUCT if (TraceBytecodesAt != 0) { @@ -3217,9 +3237,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) { // Set object alignment values. set_object_alignment(); -#ifdef SERIALGC +#if !INCLUDE_ALL_GCS force_serial_gc(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #if !INCLUDE_CDS no_shared_spaces(); #endif // INCLUDE_CDS @@ -3247,7 +3267,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { // Set heap size based on available physical memory set_heap_size(); -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS // Set per-collector flags if (UseParallelGC || UseParallelOldGC) { set_parallel_gc_flags(); @@ -3259,11 +3279,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) { set_g1_gc_flags(); } check_deprecated_gcs(); -#endif // INCLUDE_ALTERNATE_GCS - -#ifdef SERIALGC +#else // INCLUDE_ALL_GCS assert(verify_serial_gc_flags(), "SerialGC unset"); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Set bytecode rewriting flags set_bytecode_flags(); @@ -3357,7 +3375,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } jint Arguments::adjust_after_os() { -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS if (UseParallelGC || UseParallelOldGC) { if (UseNUMA) { if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) { @@ -3368,7 +3386,7 @@ jint Arguments::adjust_after_os() { UseNUMAInterleaving = true; } } -#endif +#endif // INCLUDE_ALL_GCS return JNI_OK; } @@ -3463,36 +3481,6 @@ void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, c PropertyList_add(plist, k, v); } -#ifdef KERNEL -char *Arguments::get_kernel_properties() { - // Find properties starting with kernel and append them to string - // We need to find out how long they are first because the URL's that they - // might point to could get long. - int length = 0; - SystemProperty* prop; - for (prop = _system_properties; prop != NULL; prop = prop->next()) { - if (strncmp(prop->key(), "kernel.", 7 ) == 0) { - length += (strlen(prop->key()) + strlen(prop->value()) + 5); // "-D =" - } - } - // Add one for null terminator. - char *props = AllocateHeap(length + 1, mtInternal); - if (length != 0) { - int pos = 0; - for (prop = _system_properties; prop != NULL; prop = prop->next()) { - if (strncmp(prop->key(), "kernel.", 7 ) == 0) { - jio_snprintf(&props[pos], length-pos, - "-D%s=%s ", prop->key(), prop->value()); - pos = strlen(props); - } - } - } - // null terminate props in case of null - props[length] = '\0'; - return props; -} -#endif // KERNEL - // Copies src into buf, replacing "%%" with "%" and "%p" with pid // Returns true if all of the source pointed by src has been copied over to // the destination buffer pointed by buf. Otherwise, returns false. diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 71e6e3001e9..c116e2028bb 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -540,11 +540,6 @@ class Arguments : AllStatic { // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid. static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen); - -#ifdef KERNEL - // For java kernel vm, return property string for kernel properties. - static char *get_kernel_properties(); -#endif // KERNEL }; #endif // SHARE_VM_RUNTIME_ARGUMENTS_HPP diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 63df5aa5f88..8f735b7d6fb 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1559,7 +1559,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra if (trap_method() == nm->method()) { make_not_compilable = true; } else { - trap_method->set_not_compilable(CompLevel_full_optimization); + trap_method->set_not_compilable(CompLevel_full_optimization, true, "overflow_recompile_count > PerBytecodeRecompilationCutoff"); // But give grace to the enclosing nm->method(). } } diff --git a/hotspot/src/share/vm/runtime/fprofiler.hpp b/hotspot/src/share/vm/runtime/fprofiler.hpp index c06a505630b..429b32e7f33 100644 --- a/hotspot/src/share/vm/runtime/fprofiler.hpp +++ b/hotspot/src/share/vm/runtime/fprofiler.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_RUNTIME_FPROFILER_HPP #define SHARE_VM_RUNTIME_FPROFILER_HPP +#include "utilities/macros.hpp" #include "runtime/timer.hpp" // a simple flat profiler for Java diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 569a3f4bef8..dd32cb3754c 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -29,10 +29,11 @@ #include "runtime/globals.hpp" #include "runtime/globals_extension.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_globals.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif @@ -256,9 +257,9 @@ void Flag::print_as_flag(outputStream* st) { static Flag flagTable[] = { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT) #endif diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 7ea96627e82..7db81d805bd 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -929,11 +929,14 @@ class CommandLineFlags { "Starts debugger when an implicit OS (e.g., NULL) " \ "exception happens") \ \ - notproduct(bool, PrintCodeCache, false, \ - "Print the compiled_code cache when exiting") \ + product(bool, PrintCodeCache, false, \ + "Print the code cache memory usage when exiting") \ \ develop(bool, PrintCodeCache2, false, \ - "Print detailed info on the compiled_code cache when exiting") \ + "Print detailed usage info on the code cache when exiting") \ + \ + product(bool, PrintCodeCacheOnCompilation, false, \ + "Print the code cache memory usage each time a method is compiled") \ \ diagnostic(bool, PrintStubCode, false, \ "Print generated stub code") \ @@ -969,18 +972,6 @@ class CommandLineFlags { notproduct(uintx, WarnOnStalledSpinLock, 0, \ "Prints warnings for stalled SpinLocks") \ \ - develop(bool, InitializeJavaLangSystem, true, \ - "Initialize java.lang.System - turn off for individual " \ - "method debugging") \ - \ - develop(bool, InitializeJavaLangString, true, \ - "Initialize java.lang.String - turn off for individual " \ - "method debugging") \ - \ - develop(bool, InitializeJavaLangExceptionsErrors, true, \ - "Initialize various error and exception classes - turn off for " \ - "individual method debugging") \ - \ product(bool, RegisterFinalizersAtInit, true, \ "Register finalizable objects at end of Object. or " \ "after allocation") \ @@ -1075,7 +1066,7 @@ class CommandLineFlags { \ product(intx, ClearFPUAtPark, 0, "(Unsafe,Unstable)" ) \ \ - product(intx, hashCode, 0, \ + product(intx, hashCode, 5, \ "(Unstable) select hashCode generation algorithm" ) \ \ product(intx, WorkAroundNPTLTimedWaitHang, 1, \ @@ -1166,6 +1157,18 @@ class CommandLineFlags { notproduct(bool, PrintCompactFieldsSavings, false, \ "Print how many words were saved with CompactFields") \ \ + notproduct(bool, PrintFieldLayout, false, \ + "Print field layout for each class") \ + \ + product(intx, ContendedPaddingWidth, 128, \ + "How many bytes to pad the fields/classes marked @Contended with")\ + \ + product(bool, EnableContended, true, \ + "Enable @Contended annotation support") \ + \ + product(bool, RestrictContended, true, \ + "Restrict @Contended to trusted classes") \ + \ product(bool, UseBiasedLocking, true, \ "Enable biased locking in JVM") \ \ diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp index 4d8666821a3..00d06fe276c 100644 --- a/hotspot/src/share/vm/runtime/globals_extension.hpp +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_RUNTIME_GLOBALS_EXTENSION_HPP #include "runtime/globals.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" // Construct enum of Flag_ constants. @@ -94,9 +95,9 @@ typedef enum { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER, RUNTIME_LP64_PRODUCT_FLAG_MEMBER) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER) -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER) -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER) #endif @@ -187,7 +188,7 @@ typedef enum { RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE, RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE) -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE, @@ -197,7 +198,7 @@ typedef enum { RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE, RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE) -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_MEMBER_WITH_TYPE, C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp index 541cb08676f..7ef17204bb2 100644 --- a/hotspot/src/share/vm/runtime/init.cpp +++ b/hotspot/src/share/vm/runtime/init.cpp @@ -34,6 +34,7 @@ #include "runtime/init.hpp" #include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" // Initialization done by VM thread in vm_init_globals() void check_ThreadShadow(); diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index ad6399495b0..f9be22344b1 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -64,6 +64,7 @@ #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/histogram.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" #ifdef TARGET_ARCH_x86 # include "vm_version_x86.hpp" @@ -80,11 +81,11 @@ #ifdef TARGET_ARCH_ppc # include "vm_version_ppc.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #include "c1/c1_Runtime1.hpp" @@ -368,6 +369,12 @@ void print_statistics() { if (CITime) { CompileBroker::print_times(); } + + if (PrintCodeCache) { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + CodeCache::print(); + } + #ifdef COMPILER2 if (PrintPreciseBiasedLockingStatistics) { OptoRuntime::print_named_counters(); @@ -542,6 +549,10 @@ void before_exit(JavaThread * thread) { BeforeExit_lock->notify_all(); } + // Shutdown NMT before exit. Otherwise, + // it will run into trouble when system destroys static variables. + MemTracker::shutdown(MemTracker::NMT_normal); + #undef BEFORE_EXIT_NOT_RUN #undef BEFORE_EXIT_RUNNING #undef BEFORE_EXIT_DONE diff --git a/hotspot/src/share/vm/runtime/objectMonitor.cpp b/hotspot/src/share/vm/runtime/objectMonitor.cpp index 2eefe291112..d6d2f1c3173 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -653,8 +653,7 @@ void ATTR ObjectMonitor::EnterI (TRAPS) { assert (_succ != Self, "invariant") ; if (_Responsible == Self) { _Responsible = NULL ; - // Dekker pivot-point. - // Consider OrderAccess::storeload() here + OrderAccess::fence(); // Dekker pivot-point // We may leave threads on cxq|EntryList without a designated // "Responsible" thread. This is benign. When this thread subsequently @@ -674,10 +673,6 @@ void ATTR ObjectMonitor::EnterI (TRAPS) { // // The MEMBAR, above, prevents the LD of cxq|EntryList in the subsequent // exit operation from floating above the ST Responsible=null. - // - // In *practice* however, EnterI() is always followed by some atomic - // operation such as the decrement of _count in ::enter(). Those atomics - // obviate the need for the explicit MEMBAR, above. } // We've acquired ownership with CAS(). diff --git a/hotspot/src/share/vm/runtime/objectMonitor.inline.hpp b/hotspot/src/share/vm/runtime/objectMonitor.inline.hpp index 2107523a3e8..ebe2b7dcbe2 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.inline.hpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -101,10 +101,12 @@ inline intptr_t ObjectMonitor::contentions() const { return _count; } +// Do NOT set _count = 0. There is a race such that _count could +// be set while inflating prior to setting _owner +// Just use Atomic::inc/dec and assert 0 when monitor put on free list inline void ObjectMonitor::set_owner(void* owner) { _owner = owner; _recursions = 0; - _count = 0; } diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 649ce4fcc5c..b4090680395 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -985,15 +985,28 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { // if C stack is walkable beyond current frame. The check for fp() is not // necessary on Sparc, but it's harmless. bool os::is_first_C_frame(frame* fr) { -#ifdef IA64 - // In order to walk native frames on Itanium, we need to access the unwind - // table, which is inside ELF. We don't want to parse ELF after fatal error, - // so return true for IA64. If we need to support C stack walking on IA64, - // this function needs to be moved to CPU specific files, as fp() on IA64 - // is register stack, which grows towards higher memory address. +#if defined(IA64) && !defined(_WIN32) + // On IA64 we have to check if the callers bsp is still valid + // (i.e. within the register stack bounds). + // Notice: this only works for threads created by the VM and only if + // we walk the current stack!!! If we want to be able to walk + // arbitrary other threads, we'll have to somehow store the thread + // object in the frame. + Thread *thread = Thread::current(); + if ((address)fr->fp() <= + thread->register_stack_base() HPUX_ONLY(+ 0x0) LINUX_ONLY(+ 0x50)) { + // This check is a little hacky, because on Linux the first C + // frame's ('start_thread') register stack frame starts at + // "register_stack_base + 0x48" while on HPUX, the first C frame's + // ('__pthread_bound_body') register stack frame seems to really + // start at "register_stack_base". + return true; + } else { + return false; + } +#elif defined(IA64) && defined(_WIN32) return true; -#endif - +#else // Load up sp, fp, sender sp and sender fp, check for reasonable values. // Check usp first, because if that's bad the other accessors may fault // on some architectures. Ditto ufp second, etc. @@ -1023,6 +1036,7 @@ bool os::is_first_C_frame(frame* fr) { if (old_fp - ufp > 64 * K) return true; return false; +#endif } #ifdef ASSERT diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 235005f9890..d061a0848c6 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -641,10 +641,6 @@ class os: AllStatic { static struct hostent* get_host_by_name(char* name); - // Printing 64 bit integers - static const char* jlong_format_specifier(); - static const char* julong_format_specifier(); - // Support for signals (see JVM_RaiseSignal, JVM_RegisterSignal) static void signal_init(); static void signal_init_pd(); diff --git a/hotspot/src/share/vm/runtime/perfData.cpp b/hotspot/src/share/vm/runtime/perfData.cpp index ddb565b074c..777ea27f906 100644 --- a/hotspot/src/share/vm/runtime/perfData.cpp +++ b/hotspot/src/share/vm/runtime/perfData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -192,7 +192,7 @@ PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v) } int PerfLong::format(char* buffer, int length) { - return jio_snprintf(buffer, length,"%lld", *(jlong*)_valuep); + return jio_snprintf(buffer, length, JLONG_FORMAT, *(jlong*)_valuep); } PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u, diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 76a72e4e9b7..8d0cab2a441 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -862,7 +862,15 @@ oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) { oop Reflection::new_parameter(Handle method, int index, Symbol* sym, int flags, TRAPS) { - Handle name = java_lang_String::create_from_symbol(sym, CHECK_NULL); + Handle name; + + // A null symbol here translates to the empty string + if(NULL != sym) { + name = java_lang_String::create_from_symbol(sym, CHECK_NULL); + } else { + name = java_lang_String::create_from_str("", CHECK_NULL); + } + Handle rh = java_lang_reflect_Parameter::create(CHECK_NULL); java_lang_reflect_Parameter::set_name(rh(), name()); java_lang_reflect_Parameter::set_modifiers(rh(), flags); diff --git a/hotspot/src/share/vm/runtime/safepoint.cpp b/hotspot/src/share/vm/runtime/safepoint.cpp index bf2d38c20e8..37ee19a8fbe 100644 --- a/hotspot/src/share/vm/runtime/safepoint.cpp +++ b/hotspot/src/share/vm/runtime/safepoint.cpp @@ -52,6 +52,7 @@ #include "services/memTracker.hpp" #include "services/runtimeService.hpp" #include "utilities/events.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" # include "vmreg_x86.inline.hpp" @@ -72,10 +73,10 @@ # include "nativeInst_ppc.hpp" # include "vmreg_ppc.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/shared/concurrentGCThread.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif @@ -103,7 +104,7 @@ void SafepointSynchronize::begin() { _ts_of_current_safepoint = tty->time_stamp().seconds(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseConcMarkSweepGC) { // In the future we should investigate whether CMS can use the // more-general mechanism below. DLD (01/05). @@ -111,7 +112,7 @@ void SafepointSynchronize::begin() { } else if (UseG1GC) { ConcurrentGCThread::safepoint_synchronize(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // By getting the Threads_lock, we assure that no threads are about to start or // exit. It is released again in SafepointSynchronize::end(). @@ -480,14 +481,14 @@ void SafepointSynchronize::end() { Threads_lock->unlock(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If there are any concurrent GC threads resume them. if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::desynchronize(false); } else if (UseG1GC) { ConcurrentGCThread::safepoint_desynchronize(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // record this time so VMThread can keep track how much time has elasped // since last safepoint. _end_of_last_safepoint = os::javaTimeMillis(); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 7d2b816fe63..09a0b65b958 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -56,6 +56,7 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/macros.hpp" #include "utilities/xmlstream.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" @@ -212,7 +213,7 @@ void SharedRuntime::print_ic_miss_histogram() { } #endif // PRODUCT -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // G1 write-barrier pre: executed before a pointer store. JRT_LEAF(void, SharedRuntime::g1_wb_pre(oopDesc* orig, JavaThread *thread)) @@ -230,7 +231,7 @@ JRT_LEAF(void, SharedRuntime::g1_wb_post(void* card_addr, JavaThread* thread)) thread->dirty_card_queue().enqueue(card_addr); JRT_END -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS JRT_LEAF(jlong, SharedRuntime::lmul(jlong y, jlong x)) @@ -2816,10 +2817,6 @@ VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver, JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *thread) ) -#ifdef IA64 - ShouldNotReachHere(); // NYI -#endif /* IA64 */ - // // This code is dependent on the memory layout of the interpreter local // array and the monitors. On all of our platforms the layout is identical diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index 54448890e0b..e6867645ae6 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -32,6 +32,7 @@ #include "memory/resourceArea.hpp" #include "runtime/threadLocalStorage.hpp" #include "utilities/hashtable.hpp" +#include "utilities/macros.hpp" class AdapterHandlerEntry; class AdapterHandlerTable; @@ -168,11 +169,11 @@ class SharedRuntime: AllStatic { static address raw_exception_handler_for_return_address(JavaThread* thread, address return_address); static address exception_handler_for_return_address(JavaThread* thread, address return_address); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // G1 write barriers static void g1_wb_pre(oopDesc* orig, JavaThread *thread); static void g1_wb_post(void* card_addr, JavaThread* thread); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // exception handling and implicit exceptions static address compute_compiled_exc_handler(nmethod* nm, address ret_pc, Handle& exception, diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index 13b71cb806f..bdf416275dc 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -53,7 +53,7 @@ # include "os_bsd.inline.hpp" #endif -#if defined(__GNUC__) && !defined(IA64) +#if defined(__GNUC__) // Need to inhibit inlining for older versions of GCC to avoid build-time failures #define ATTR __attribute__((noinline)) #else @@ -333,7 +333,9 @@ bool ObjectSynchronizer::jni_try_enter(Handle obj, Thread* THREAD) { void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) { TEVENT (jni_exit) ; if (UseBiasedLocking) { - BiasedLocking::revoke_and_rebias(obj, false, THREAD); + Handle h_obj(THREAD, obj); + BiasedLocking::revoke_and_rebias(h_obj, false, THREAD); + obj = h_obj(); } assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index db3cace3d64..e0cf75b03f2 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,6 +82,7 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/preserveException.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" #endif @@ -94,11 +95,11 @@ #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" #include "gc_implementation/parallelScavenge/pcTasks.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #endif @@ -1482,17 +1483,17 @@ void JavaThread::initialize() { pd_initialize(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS SATBMarkQueueSet JavaThread::_satb_mark_queue_set; DirtyCardQueueSet JavaThread::_dirty_card_queue_set; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS JavaThread::JavaThread(bool is_attaching_via_jni) : Thread() -#ifndef SERIALGC +#if INCLUDE_ALL_GCS , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS { initialize(); if (is_attaching_via_jni) { @@ -1500,7 +1501,7 @@ JavaThread::JavaThread(bool is_attaching_via_jni) : } else { _jni_attach_state = _not_attaching_via_jni; } - assert(_deferred_card_mark.is_empty(), "Default MemRegion ctor"); + assert(deferred_card_mark().is_empty(), "Default MemRegion ctor"); _safepoint_visible = false; } @@ -1547,10 +1548,10 @@ static void compiler_thread_entry(JavaThread* thread, TRAPS); JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) : Thread() -#ifndef SERIALGC +#if INCLUDE_ALL_GCS , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS { if (TraceThreadEvents) { tty->print_cr("creating thread %p", this); @@ -1716,7 +1717,6 @@ static void ensure_join(JavaThread* thread) { // cleanup_failed_attach_current_thread as well. void JavaThread::exit(bool destroy_vm, ExitType exit_type) { assert(this == JavaThread::current(), "thread consistency check"); - if (!InitializeJavaLangSystem) return; HandleMark hm(this); Handle uncaught_exception(this, this->pending_exception()); @@ -1897,19 +1897,26 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { JvmtiExport::cleanup_thread(this); } -#ifndef SERIALGC - // We must flush G1-related buffers before removing a thread from + // We must flush any deferred card marks before removing a thread from // the list of active threads. + Universe::heap()->flush_deferred_store_barrier(this); + assert(deferred_card_mark().is_empty(), "Should have been flushed"); + +#if INCLUDE_ALL_GCS + // We must flush the G1-related buffers before removing a thread + // from the list of active threads. We must do this after any deferred + // card marks have been flushed (above) so that any entries that are + // added to the thread's dirty card queue as a result are not lost. if (UseG1GC) { flush_barrier_queues(); } -#endif +#endif // INCLUDE_ALL_GCS // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Flush G1-related queues. void JavaThread::flush_barrier_queues() { satb_mark_queue().flush(); @@ -1937,7 +1944,7 @@ void JavaThread::initialize_queues() { // active field set to true. assert(dirty_queue.is_active(), "dirty card queue should be active"); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS void JavaThread::cleanup_failed_attach_current_thread() { if (get_thread_profiler() != NULL) { @@ -1965,11 +1972,11 @@ void JavaThread::cleanup_failed_attach_current_thread() { tlab().make_parsable(true); // retire TLAB, if any } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { flush_barrier_queues(); } -#endif +#endif // INCLUDE_ALL_GCS Threads::remove(this); delete this; @@ -3469,11 +3476,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { create_vm_init_libraries(); } - if (InitializeJavaLangString) { - initialize_class(vmSymbols::java_lang_String(), CHECK_0); - } else { - warning("java.lang.String not initialized"); - } + initialize_class(vmSymbols::java_lang_String(), CHECK_0); if (AggressiveOpts) { { @@ -3514,53 +3517,39 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { } // Initialize java_lang.System (needed before creating the thread) - if (InitializeJavaLangSystem) { - initialize_class(vmSymbols::java_lang_System(), CHECK_0); - initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0); - Handle thread_group = create_initial_thread_group(CHECK_0); - Universe::set_main_thread_group(thread_group()); - initialize_class(vmSymbols::java_lang_Thread(), CHECK_0); - oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0); - main_thread->set_threadObj(thread_object); - // Set thread status to running since main thread has - // been started and running. - java_lang_Thread::set_thread_status(thread_object, - java_lang_Thread::RUNNABLE); + initialize_class(vmSymbols::java_lang_System(), CHECK_0); + initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0); + Handle thread_group = create_initial_thread_group(CHECK_0); + Universe::set_main_thread_group(thread_group()); + initialize_class(vmSymbols::java_lang_Thread(), CHECK_0); + oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0); + main_thread->set_threadObj(thread_object); + // Set thread status to running since main thread has + // been started and running. + java_lang_Thread::set_thread_status(thread_object, + java_lang_Thread::RUNNABLE); - // The VM creates & returns objects of this class. Make sure it's initialized. - initialize_class(vmSymbols::java_lang_Class(), CHECK_0); + // The VM creates & returns objects of this class. Make sure it's initialized. + initialize_class(vmSymbols::java_lang_Class(), CHECK_0); - // The VM preresolves methods to these classes. Make sure that they get initialized - initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0); - initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK_0); - call_initializeSystemClass(CHECK_0); + // The VM preresolves methods to these classes. Make sure that they get initialized + initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0); + initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK_0); + call_initializeSystemClass(CHECK_0); - // get the Java runtime name after java.lang.System is initialized - JDK_Version::set_runtime_name(get_java_runtime_name(THREAD)); - JDK_Version::set_runtime_version(get_java_runtime_version(THREAD)); - } else { - warning("java.lang.System not initialized"); - } + // get the Java runtime name after java.lang.System is initialized + JDK_Version::set_runtime_name(get_java_runtime_name(THREAD)); + JDK_Version::set_runtime_version(get_java_runtime_version(THREAD)); // an instance of OutOfMemory exception has been allocated earlier - if (InitializeJavaLangExceptionsErrors) { - initialize_class(vmSymbols::java_lang_OutOfMemoryError(), CHECK_0); - initialize_class(vmSymbols::java_lang_NullPointerException(), CHECK_0); - initialize_class(vmSymbols::java_lang_ClassCastException(), CHECK_0); - initialize_class(vmSymbols::java_lang_ArrayStoreException(), CHECK_0); - initialize_class(vmSymbols::java_lang_ArithmeticException(), CHECK_0); - initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK_0); - initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK_0); - initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK_0); - } else { - warning("java.lang.OutOfMemoryError has not been initialized"); - warning("java.lang.NullPointerException has not been initialized"); - warning("java.lang.ClassCastException has not been initialized"); - warning("java.lang.ArrayStoreException has not been initialized"); - warning("java.lang.ArithmeticException has not been initialized"); - warning("java.lang.StackOverflowError has not been initialized"); - warning("java.lang.IllegalArgumentException has not been initialized"); - } + initialize_class(vmSymbols::java_lang_OutOfMemoryError(), CHECK_0); + initialize_class(vmSymbols::java_lang_NullPointerException(), CHECK_0); + initialize_class(vmSymbols::java_lang_ClassCastException(), CHECK_0); + initialize_class(vmSymbols::java_lang_ArrayStoreException(), CHECK_0); + initialize_class(vmSymbols::java_lang_ArithmeticException(), CHECK_0); + initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK_0); + initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK_0); + initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK_0); } // See : bugid 4211085. @@ -3619,7 +3608,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Support for ConcurrentMarkSweep. This should be cleaned up // and better encapsulated. The ugly nested if test would go away // once things are properly refactored. XXX YSR @@ -3633,7 +3622,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution @@ -3758,28 +3747,6 @@ static OnLoadEntry_t lookup_on_load(AgentLibrary* agent, const char *on_load_sym name)) { library = os::dll_load(buffer, ebuf, sizeof ebuf); } -#ifdef KERNEL - // Download instrument dll - if (library == NULL && strcmp(name, "instrument") == 0) { - char *props = Arguments::get_kernel_properties(); - char *home = Arguments::get_java_home(); - const char *fmt = "%s/bin/java %s -Dkernel.background.download=false" - " sun.jkernel.DownloadManager -download client_jvm"; - size_t length = strlen(props) + strlen(home) + strlen(fmt) + 1; - char *cmd = NEW_C_HEAP_ARRAY(char, length, mtThread); - jio_snprintf(cmd, length, fmt, home, props); - int status = os::fork_and_exec(cmd); - FreeHeap(props); - if (status == -1) { - warning(cmd); - vm_exit_during_initialization("fork_and_exec failed: %s", - strerror(errno)); - } - FREE_C_HEAP_ARRAY(char, cmd, mtThread); - // when this comes back the instrument.dll should be where it belongs. - library = os::dll_load(buffer, ebuf, sizeof ebuf); - } -#endif // KERNEL if (library == NULL) { // Try the local directory char ns[1] = {0}; if (os::dll_build_name(buffer, sizeof(buffer), ns, name)) { @@ -4011,10 +3978,6 @@ bool Threads::destroy_vm() { Mutex::_as_suspend_equivalent_flag); } - // Shutdown NMT before exit. Otherwise, - // it will run into trouble when system destroys static variables. - MemTracker::shutdown(MemTracker::NMT_normal); - // Hang forever on exit if we are reporting an error. if (ShowMessageBoxOnError && is_error_reported()) { os::infinite_sleep(); @@ -4232,7 +4195,7 @@ void Threads::possibly_parallel_oops_do(OopClosure* f, CLDToOopClosure* cld_f, C } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Used by ParallelScavenge void Threads::create_thread_roots_tasks(GCTaskQueue* q) { ALL_JAVA_THREADS(p) { @@ -4248,7 +4211,7 @@ void Threads::create_thread_roots_marking_tasks(GCTaskQueue* q) { } q->enqueue(new ThreadRootsMarkingTask(VMThread::vm_thread())); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void Threads::nmethods_do(CodeBlobClosure* cf) { ALL_JAVA_THREADS(p) { @@ -4356,13 +4319,13 @@ void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format ); st->cr(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Dump concurrent locks ConcurrentLocksDump concurrent_locks; if (print_concurrent_locks) { concurrent_locks.dump_at_safepoint(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_JAVA_THREADS(p) { ResourceMark rm; @@ -4375,11 +4338,11 @@ void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format } } st->cr(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (print_concurrent_locks) { concurrent_locks.print_locks_on(p, st); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } VMThread::vm_thread()->print_on(st); diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 627000c7233..98f8d254545 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -41,6 +41,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/threadLocalStorage.hpp" #include "runtime/unhandledOops.hpp" +#include "utilities/macros.hpp" #if INCLUDE_NMT #include "services/memRecorder.hpp" @@ -49,10 +50,10 @@ #include "trace/tracing.hpp" #include "utilities/exceptions.hpp" #include "utilities/top.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/dirtyCardQueue.hpp" #include "gc_implementation/g1/satbQueue.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef ZERO #ifdef TARGET_ARCH_zero # include "stack_zero.hpp" @@ -929,7 +930,7 @@ class JavaThread: public Thread { } _jmp_ring[ jump_ring_buffer_size ]; #endif /* PRODUCT */ -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Support for G1 barriers ObjPtrQueue _satb_mark_queue; // Thread-local log for SATB barrier. @@ -941,7 +942,7 @@ class JavaThread: public Thread { static DirtyCardQueueSet _dirty_card_queue_set; void flush_barrier_queues(); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS friend class VMThread; friend class ThreadWaitTransition; @@ -1345,10 +1346,10 @@ class JavaThread: public Thread { return byte_offset_of(JavaThread, _should_post_on_exceptions_flag); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS static ByteSize satb_mark_queue_offset() { return byte_offset_of(JavaThread, _satb_mark_queue); } static ByteSize dirty_card_queue_offset() { return byte_offset_of(JavaThread, _dirty_card_queue); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Returns the jni environment for this thread JNIEnv* jni_environment() { return &_jni_environment; } @@ -1637,7 +1638,7 @@ public: _stack_size_at_create = value; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // SATB marking queue support ObjPtrQueue& satb_mark_queue() { return _satb_mark_queue; } static SATBMarkQueueSet& satb_mark_queue_set() { @@ -1649,7 +1650,7 @@ public: static DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // This method initializes the SATB and dirty card queues before a // JavaThread is added to the Java thread list. Right now, we don't @@ -1668,11 +1669,11 @@ public: // might happen between the JavaThread constructor being called and the // thread being added to the Java thread list (an example of this is // when the structure for the DestroyJavaVM thread is created). -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void initialize_queues(); -#else // !SERIALGC +#else // INCLUDE_ALL_GCS void initialize_queues() { } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Machine dependent stuff #ifdef TARGET_OS_ARCH_linux_x86 diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 2c9aa0f3adb..d00e9f00954 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -233,8 +233,6 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, // Force early return from top frame after deoptimization #ifndef CC_INTERP pc = Interpreter::remove_activation_early_entry(state->earlyret_tos()); -#else - // TBD: Need to implement ForceEarlyReturn for CC_INTERP (ia64) #endif } else { // Possibly override the previous pc computation of the top (youngest) frame diff --git a/hotspot/src/share/vm/runtime/virtualspace.cpp b/hotspot/src/share/vm/runtime/virtualspace.cpp index f33c1995e34..dffb588dbae 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.cpp +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -868,8 +868,8 @@ void VirtualSpace::print() { tty->print ("Virtual space:"); if (special()) tty->print(" (pinned in memory)"); tty->cr(); - tty->print_cr(" - committed: %ld", committed_size()); - tty->print_cr(" - reserved: %ld", reserved_size()); + tty->print_cr(" - committed: " SIZE_FORMAT, committed_size()); + tty->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); tty->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); } diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 9ac10e26d4c..86169fcfc34 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -101,6 +101,7 @@ #include "utilities/array.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/hashtable.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "vmStructs_x86.hpp" #endif @@ -146,7 +147,7 @@ #ifdef TARGET_OS_ARCH_bsd_zero # include "vmStructs_bsd_zero.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" @@ -161,7 +162,7 @@ #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/parallelScavenge/vmStructs_parallelgc.hpp" #include "gc_implementation/g1/vmStructs_g1.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER2 #include "opto/addnode.hpp" #include "opto/block.hpp" @@ -257,8 +258,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; c1_nonstatic_field, \ c2_nonstatic_field, \ unchecked_c1_static_field, \ - unchecked_c2_static_field, \ - last_entry) \ + unchecked_c2_static_field) \ \ /******************************************************************/ \ /* OopDesc and Klass hierarchies (NOTE: MethodData* incomplete) */ \ @@ -718,7 +718,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \ \ static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \ - nonstatic_field(ClassLoaderDataGraph, _unloading, ClassLoaderData*) \ \ /*******************/ \ /* GrowableArrays */ \ @@ -1163,6 +1162,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; static_field(Abstract_VM_Version, _vm_major_version, int) \ static_field(Abstract_VM_Version, _vm_minor_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) \ nonstatic_field(JDK_Version, _partially_initialized, bool) \ @@ -1200,7 +1200,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /*********************************/ \ \ static_field(java_lang_Class, _klass_offset, int) \ - static_field(java_lang_Class, _resolved_constructor_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) \ @@ -1238,9 +1237,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(FreeList, _count, ssize_t) \ nonstatic_field(MetablockTreeDictionary, _total_size, size_t) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ - /* be present there) */ //-------------------------------------------------------------------------------- // VM_TYPES @@ -1280,8 +1276,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_unsigned_integer_type, \ declare_c1_toplevel_type, \ declare_c2_type, \ - declare_c2_toplevel_type, \ - last_entry) \ + declare_c2_toplevel_type) \ \ /*************************************************************/ \ /* Java primitive types -- required by the SA implementation */ \ @@ -2094,14 +2089,9 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_toplevel_type(FreeBlockDictionary*) \ declare_toplevel_type(FreeList*) \ declare_toplevel_type(FreeList) \ - declare_toplevel_type(MetablockTreeDictionary*) \ - declare_type(MetablockTreeDictionary, FreeBlockDictionary) + declare_type(MetablockTreeDictionary, FreeBlockDictionary) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must be */ - /* present there) */ - //-------------------------------------------------------------------------------- // VM_INT_CONSTANTS // @@ -2114,8 +2104,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_preprocessor_constant, \ declare_c1_constant, \ declare_c2_constant, \ - declare_c2_preprocessor_constant, \ - last_entry) \ + declare_c2_preprocessor_constant) \ \ /******************/ \ /* Useful globals */ \ @@ -2294,10 +2283,18 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_constant(FieldInfo::name_index_offset) \ declare_constant(FieldInfo::signature_index_offset) \ declare_constant(FieldInfo::initval_index_offset) \ - declare_constant(FieldInfo::low_offset) \ - declare_constant(FieldInfo::high_offset) \ + declare_constant(FieldInfo::low_packed_offset) \ + declare_constant(FieldInfo::high_packed_offset) \ declare_constant(FieldInfo::field_slots) \ \ + /*************************************/ \ + /* FieldInfo tag constants */ \ + /*************************************/ \ + \ + declare_preprocessor_constant("FIELDINFO_TAG_SIZE", FIELDINFO_TAG_SIZE) \ + declare_preprocessor_constant("FIELDINFO_TAG_MASK", FIELDINFO_TAG_MASK) \ + declare_preprocessor_constant("FIELDINFO_TAG_OFFSET", FIELDINFO_TAG_OFFSET) \ + \ /************************************************/ \ /* InstanceKlass InnerClassAttributeOffset enum */ \ /************************************************/ \ @@ -2483,9 +2480,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_c2_preprocessor_constant("SAVED_ON_ENTRY_REG_COUNT", SAVED_ON_ENTRY_REG_COUNT) \ declare_c2_preprocessor_constant("C_SAVED_ON_ENTRY_REG_COUNT", C_SAVED_ON_ENTRY_REG_COUNT) - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and */ - /* must be present there) */ //-------------------------------------------------------------------------------- // VM_LONG_CONSTANTS @@ -2495,7 +2489,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; // enums, etc., while "declare_preprocessor_constant" must be used for // all #defined constants. -#define VM_LONG_CONSTANTS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ +#define VM_LONG_CONSTANTS(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ \ /*********************/ \ /* MarkOop constants */ \ @@ -2541,11 +2535,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /* Constants in markOop used by CMS. */ \ declare_constant(markOopDesc::cms_shift) \ declare_constant(markOopDesc::cms_mask) \ - declare_constant(markOopDesc::size_shift) \ - - /* NOTE that we do not use the last_entry() macro here; it is used */ - /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and */ - /* must be present there) */ + declare_constant(markOopDesc::size_shift) //-------------------------------------------------------------------------------- @@ -2585,7 +2575,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; // This macro checks the type of a VMStructEntry by comparing pointer types #define CHECK_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ - {typeName *dummyObj = NULL; type* dummy = &dummyObj->fieldName; } + {typeName *dummyObj = NULL; type* dummy = &dummyObj->fieldName; \ + assert(offset_of(typeName, fieldName) < sizeof(typeName), "Illegal nonstatic struct entry, field offset too large"); } // This macro checks the type of a volatile VMStructEntry by comparing pointer types #define CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ @@ -2608,9 +2599,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; // This is a no-op macro for unchecked fields #define CHECK_NO_OP(a, b, c) -// This is a no-op macro for the sentinel value -#define CHECK_SENTINEL() - // // Build-specific macros: // @@ -2789,48 +2777,47 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; // as long as class VMStructs is a friend VMStructEntry VMStructs::localHotSpotVMStructs[] = { - VM_STRUCTS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C1_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_VM_STRUCT_LAST_ENTRY) + VM_STRUCTS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_STATIC_VM_STRUCT_ENTRY, + GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C1_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, + GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) -#ifndef SERIALGC - VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ +#if INCLUDE_ALL_GCS + VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) - VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ + VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) - VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ + VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS - VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_VM_STRUCT_LAST_ENTRY) + VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_STATIC_VM_STRUCT_ENTRY, + GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, + GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) - VM_STRUCTS_OS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, \ - GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY, \ - GENERATE_VM_STRUCT_LAST_ENTRY) + VM_STRUCTS_OS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_STATIC_VM_STRUCT_ENTRY, + GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C2_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, + GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) + + GENERATE_VM_STRUCT_LAST_ENTRY() }; VMTypeEntry VMStructs::localHotSpotVMTypes[] = { @@ -2842,10 +2829,9 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_VM_TYPE_LAST_ENTRY) + GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_TYPES_PARALLELGC(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY) @@ -2856,7 +2842,7 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { VM_TYPES_G1(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, @@ -2865,8 +2851,7 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_VM_TYPE_LAST_ENTRY) + GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) VM_TYPES_OS_CPU(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, @@ -2875,8 +2860,9 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY, GENERATE_C1_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_C2_VM_TYPE_ENTRY, - GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY, - GENERATE_VM_TYPE_LAST_ENTRY) + GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) + + GENERATE_VM_TYPE_LAST_ENTRY() }; VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { @@ -2885,28 +2871,27 @@ VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, GENERATE_C1_VM_INT_CONSTANT_ENTRY, GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_VM_INT_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY) VM_INT_CONSTANTS_PARNEW(GENERATE_VM_INT_CONSTANT_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_INT_CONSTANTS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, GENERATE_C1_VM_INT_CONSTANT_ENTRY, GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_VM_INT_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) VM_INT_CONSTANTS_OS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, GENERATE_C1_VM_INT_CONSTANT_ENTRY, GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, - GENERATE_VM_INT_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) + + GENERATE_VM_INT_CONSTANT_LAST_ENTRY() }; VMLongConstantEntry VMStructs::localHotSpotVMLongConstants[] = { @@ -2915,22 +2900,21 @@ VMLongConstantEntry VMStructs::localHotSpotVMLongConstants[] = { GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, GENERATE_C1_VM_LONG_CONSTANT_ENTRY, GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_VM_LONG_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) VM_LONG_CONSTANTS_CPU(GENERATE_VM_LONG_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, GENERATE_C1_VM_LONG_CONSTANT_ENTRY, GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_VM_LONG_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) VM_LONG_CONSTANTS_OS_CPU(GENERATE_VM_LONG_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, GENERATE_C1_VM_LONG_CONSTANT_ENTRY, GENERATE_C2_VM_LONG_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY, - GENERATE_VM_LONG_CONSTANT_LAST_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY) + + GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() }; // This is used both to check the types of referenced fields and, in @@ -2945,10 +2929,9 @@ VMStructs::init() { CHECK_C1_NONSTATIC_VM_STRUCT_ENTRY, CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, - CHECK_NO_OP, - CHECK_SENTINEL); + CHECK_NO_OP); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_STRUCTS_PARALLELGC(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); @@ -2958,7 +2941,7 @@ VMStructs::init() { VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, @@ -2967,8 +2950,7 @@ VMStructs::init() { CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, - CHECK_NO_OP, - CHECK_SENTINEL); + CHECK_NO_OP); VM_STRUCTS_OS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, @@ -2977,8 +2959,7 @@ VMStructs::init() { CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY, CHECK_C2_NONSTATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, - CHECK_NO_OP, - CHECK_SENTINEL); + CHECK_NO_OP); VM_TYPES(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, @@ -2987,10 +2968,9 @@ VMStructs::init() { CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_SENTINEL); + CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_TYPES_PARALLELGC(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP); @@ -3001,7 +2981,7 @@ VMStructs::init() { VM_TYPES_G1(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, @@ -3010,8 +2990,7 @@ VMStructs::init() { CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_SENTINEL); + CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); VM_TYPES_OS_CPU(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, @@ -3020,8 +2999,7 @@ VMStructs::init() { CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_C1_TOPLEVEL_VM_TYPE_ENTRY, CHECK_C2_VM_TYPE_ENTRY, - CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY, - CHECK_SENTINEL); + CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); // // Split VM_STRUCTS() invocation into two parts to allow MS VC++ 6.0 @@ -3040,53 +3018,49 @@ VMStructs::init() { // Solstice NFS setup. If everyone switches to local workspaces on // Win32, we can put this back in. #ifndef _WINDOWS - debug_only(VM_STRUCTS(ENSURE_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_SENTINEL)); - debug_only(VM_STRUCTS(CHECK_NO_OP, \ - ENSURE_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, \ - ENSURE_C1_FIELD_TYPE_PRESENT, \ - ENSURE_C2_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_SENTINEL)); -#ifndef SERIALGC - debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, \ + debug_only(VM_STRUCTS(ENSURE_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP, + CHECK_NO_OP)); + debug_only(VM_STRUCTS(CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, + ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, + ENSURE_C1_FIELD_TYPE_PRESENT, + ENSURE_C2_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + CHECK_NO_OP)); +#if INCLUDE_ALL_GCS + debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); - debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_FIELD_TYPE_PRESENT, \ + debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, + ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); - debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT, \ + debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); -#endif // SERIALGC - debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, \ - ENSURE_C2_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_SENTINEL)); - debug_only(VM_STRUCTS_OS_CPU(ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - ENSURE_FIELD_TYPE_PRESENT, \ - ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, \ - ENSURE_C2_FIELD_TYPE_PRESENT, \ - CHECK_NO_OP, \ - CHECK_NO_OP, \ - CHECK_SENTINEL)); +#endif // INCLUDE_ALL_GCS + debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, + ENSURE_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, + ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, + ENSURE_C2_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + CHECK_NO_OP)); + debug_only(VM_STRUCTS_OS_CPU(ENSURE_FIELD_TYPE_PRESENT, + ENSURE_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + ENSURE_FIELD_TYPE_PRESENT, + ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT, + ENSURE_C2_FIELD_TYPE_PRESENT, + CHECK_NO_OP, + CHECK_NO_OP)); #endif } @@ -3146,10 +3120,10 @@ static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool s[len-1] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { - delete s; + delete [] s; return 1; } - delete s; + delete [] s; } const char* start = NULL; if (strstr(typeName, "GrowableArray<") == typeName) { @@ -3165,10 +3139,10 @@ static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool s[len-1] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { - delete s; + delete [] s; return 1; } - delete s; + delete [] s; } if (strstr(typeName, "const ") == typeName) { const char * s = typeName + strlen("const "); @@ -3182,8 +3156,10 @@ static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool s[len - 6] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { + free(s); return 1; } + free(s); } if (!isRecurse) { tty->print_cr("type \"%s\" not found", typeName); @@ -3206,6 +3182,30 @@ void vmStructs_init() { #ifndef PRODUCT void VMStructs::test() { + // Make sure last entry in the each array is indeed the correct end marker. + // The reason why these are static is to make sure they are zero initialized. + // Putting them on the stack will leave some garbage in the padding of some fields. + static VMStructEntry struct_last_entry = GENERATE_VM_STRUCT_LAST_ENTRY(); + assert(memcmp(&localHotSpotVMStructs[(sizeof(localHotSpotVMStructs) / sizeof(VMStructEntry)) - 1], + &struct_last_entry, + sizeof(VMStructEntry)) == 0, "Incorrect last entry in localHotSpotVMStructs"); + + static VMTypeEntry type_last_entry = GENERATE_VM_TYPE_LAST_ENTRY(); + assert(memcmp(&localHotSpotVMTypes[sizeof(localHotSpotVMTypes) / sizeof(VMTypeEntry) - 1], + &type_last_entry, + sizeof(VMTypeEntry)) == 0, "Incorrect last entry in localHotSpotVMTypes"); + + static VMIntConstantEntry int_last_entry = GENERATE_VM_INT_CONSTANT_LAST_ENTRY(); + assert(memcmp(&localHotSpotVMIntConstants[sizeof(localHotSpotVMIntConstants) / sizeof(VMIntConstantEntry) - 1], + &int_last_entry, + sizeof(VMIntConstantEntry)) == 0, "Incorrect last entry in localHotSpotVMIntConstants"); + + static VMLongConstantEntry long_last_entry = GENERATE_VM_LONG_CONSTANT_LAST_ENTRY(); + assert(memcmp(&localHotSpotVMLongConstants[sizeof(localHotSpotVMLongConstants) / sizeof(VMLongConstantEntry) - 1], + &long_last_entry, + sizeof(VMLongConstantEntry)) == 0, "Incorrect last entry in localHotSpotVMLongConstants"); + + // Check for duplicate entries in type array for (int i = 0; localHotSpotVMTypes[i].typeName != NULL; i++) { for (int j = i + 1; localHotSpotVMTypes[j].typeName != NULL; j++) { diff --git a/hotspot/src/share/vm/runtime/vmStructs.hpp b/hotspot/src/share/vm/runtime/vmStructs.hpp index b1070a406e2..5c4c93a1f77 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.hpp +++ b/hotspot/src/share/vm/runtime/vmStructs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -25,9 +25,7 @@ #ifndef SHARE_VM_RUNTIME_VMSTRUCTS_HPP #define SHARE_VM_RUNTIME_VMSTRUCTS_HPP -#ifndef VM_STRUCTS_KERNEL #include "utilities/debug.hpp" -#endif #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index d8d3e444780..286d457c997 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -570,7 +570,11 @@ void VMThread::execute(VM_Operation* op) { if (!t->is_VM_thread()) { SkipGCALot sgcalot(t); // avoid re-entrant attempts to gc-a-lot // JavaThread or WatcherThread - t->check_for_valid_safepoint_state(true); + bool concurrent = op->evaluate_concurrently(); + // only blocking VM operations need to verify the caller's safepoint state: + if (!concurrent) { + t->check_for_valid_safepoint_state(true); + } // New request from Java thread, evaluate prologue if (!op->doit_prologue()) { @@ -582,7 +586,6 @@ void VMThread::execute(VM_Operation* op) { // It does not make sense to execute the epilogue, if the VM operation object is getting // deallocated by the VM thread. - bool concurrent = op->evaluate_concurrently(); bool execute_epilog = !op->is_cheap_allocated(); assert(!concurrent || op->is_cheap_allocated(), "concurrent => cheap_allocated"); diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index 2d105a97baf..ef03c76f62b 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -111,9 +111,6 @@ void Abstract_VM_Version::initialize() { #endif #ifndef VMTYPE - #ifdef KERNEL - #define VMTYPE "Kernel" - #else // KERNEL #ifdef TIERED #define VMTYPE "Server" #else // TIERED @@ -128,7 +125,6 @@ void Abstract_VM_Version::initialize() { COMPILER2_PRESENT("Server") #endif // ZERO #endif // TIERED - #endif // KERNEL #endif #ifndef HOTSPOT_VM_DISTRO diff --git a/hotspot/src/share/vm/services/attachListener.cpp b/hotspot/src/share/vm/services/attachListener.cpp index 80dfd7effd4..da93859bb94 100644 --- a/hotspot/src/share/vm/services/attachListener.cpp +++ b/hotspot/src/share/vm/services/attachListener.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -170,7 +170,6 @@ static jint jcmd(AttachOperation* op, outputStream* out) { return JNI_OK; } -#ifndef SERVICES_KERNEL // Heap dumping not supported // Implementation of "dumpheap" command. // See also: HeapDumpDCmd class // @@ -212,7 +211,6 @@ jint dump_heap(AttachOperation* op, outputStream* out) { } return JNI_OK; } -#endif // SERVICES_KERNEL // Implementation of "inspectheap" command // See also: ClassHistogramDCmd class @@ -382,9 +380,7 @@ static jint print_flag(AttachOperation* op, outputStream* out) { static AttachOperationFunctionInfo funcs[] = { { "agentProperties", get_agent_properties }, { "datadump", data_dump }, -#ifndef SERVICES_KERNEL { "dumpheap", dump_heap }, -#endif // SERVICES_KERNEL { "load", JvmtiExport::load_agent_library }, { "properties", get_system_properties }, { "threaddump", thread_dump }, diff --git a/hotspot/src/share/vm/services/attachListener.hpp b/hotspot/src/share/vm/services/attachListener.hpp index 1916e8cacb8..2e7cff39537 100644 --- a/hotspot/src/share/vm/services/attachListener.hpp +++ b/hotspot/src/share/vm/services/attachListener.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "utilities/debug.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" // The AttachListener thread services a queue of operations that are enqueued // by client tools. Each operation is identified by a name and has up to 3 @@ -38,8 +39,6 @@ // complets the result value and any result data is returned to the client // tool. -#ifndef SERVICES_KERNEL - class AttachOperation; typedef jint (*AttachOperationFunction)(AttachOperation* op, outputStream* out); @@ -48,7 +47,6 @@ struct AttachOperationFunctionInfo { const char* name; AttachOperationFunction func; }; -#endif // SERVICES_KERNEL class AttachListener: AllStatic { public: diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 04dfca89211..b06890808ab 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -31,6 +31,7 @@ #include "services/classLoadingService.hpp" #include "services/memoryService.hpp" #include "utilities/dtrace.hpp" +#include "utilities/macros.hpp" #ifdef DTRACE_ENABLED diff --git a/hotspot/src/share/vm/services/classLoadingService.hpp b/hotspot/src/share/vm/services/classLoadingService.hpp index 1ea177f8352..a7f2c4c254a 100644 --- a/hotspot/src/share/vm/services/classLoadingService.hpp +++ b/hotspot/src/share/vm/services/classLoadingService.hpp @@ -28,6 +28,7 @@ #include "runtime/handles.hpp" #include "runtime/perfData.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" class InstanceKlass; diff --git a/hotspot/src/share/vm/services/diagnosticArgument.cpp b/hotspot/src/share/vm/services/diagnosticArgument.cpp index 826b530bcb2..5d0eb756b28 100644 --- a/hotspot/src/share/vm/services/diagnosticArgument.cpp +++ b/hotspot/src/share/vm/services/diagnosticArgument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -86,7 +86,7 @@ void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) { template <> void DCmdArgument::parse_value(const char* str, size_t len, TRAPS) { - if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) { + if (str == NULL || sscanf(str, JLONG_FORMAT, &_value) != 1) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Integer parsing error in diagnostic command arguments\n"); } @@ -171,7 +171,7 @@ template <> void DCmdArgument::parse_value(const char* str, "Integer parsing error nanotime value: syntax error"); } - int argc = sscanf(str, INT64_FORMAT , &_value._time); + int argc = sscanf(str, JLONG_FORMAT, &_value._time); if (argc != 1) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Integer parsing error nanotime value: syntax error"); diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 52a098a2613..5499d9ad2fe 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -30,6 +30,7 @@ #include "services/diagnosticFramework.hpp" #include "services/heapDumper.hpp" #include "services/management.hpp" +#include "utilities/macros.hpp" void DCmdRegistrant::register_dcmds(){ // Registration of the diagnostic commands @@ -43,12 +44,12 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#endif // INCLUDE_SERVICES DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); +#endif // INCLUDE_SERVICES DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - //Enhanced JMX Agent Support DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true,false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true,false)); @@ -252,7 +253,7 @@ void RunFinalizationDCmd::execute(TRAPS) { vmSymbols::void_method_signature(), CHECK); } -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _filename("filename","Name of the dump file", "STRING",true), @@ -292,7 +293,6 @@ int HeapDumpDCmd::num_arguments() { return 0; } } -#endif // INCLUDE_SERVICES ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), @@ -319,6 +319,65 @@ int ClassHistogramDCmd::num_arguments() { } } +#define DEFAULT_COLUMNS "InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total" +ClassStatsDCmd::ClassStatsDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap), + _csv("-csv", "Print in CSV (comma-separated values) format for spreadsheets", + "BOOLEAN", false, "false"), + _all("-all", "Show all columns", + "BOOLEAN", false, "false"), + _help("-help", "Show meaning of all the columns", + "BOOLEAN", false, "false"), + _columns("columns", "Comma-separated list of all the columns to show. " + "If not specified, the following columns are shown: " DEFAULT_COLUMNS, + "STRING", false) { + _dcmdparser.add_dcmd_option(&_all); + _dcmdparser.add_dcmd_option(&_csv); + _dcmdparser.add_dcmd_option(&_help); + _dcmdparser.add_dcmd_argument(&_columns); +} + +void ClassStatsDCmd::execute(TRAPS) { + if (!UnlockDiagnosticVMOptions) { + output()->print_cr("GC.class_stats command requires -XX:+UnlockDiagnosticVMOptions"); + return; + } + + VM_GC_HeapInspection heapop(output(), + true, /* request_full_gc */ + true /* need_prologue */); + heapop.set_csv_format(_csv.value()); + heapop.set_print_help(_help.value()); + heapop.set_print_class_stats(true); + if (_all.value()) { + if (_columns.has_value()) { + output()->print_cr("Cannot specify -all and individual columns at the same time"); + return; + } else { + heapop.set_columns(NULL); + } + } else { + if (_columns.has_value()) { + heapop.set_columns(_columns.value()); + } else { + heapop.set_columns(DEFAULT_COLUMNS); + } + } + VMThread::execute(&heapop); +} + +int ClassStatsDCmd::num_arguments() { + ResourceMark rm; + ClassStatsDCmd* dcmd = new ClassStatsDCmd(NULL, false); + if (dcmd != NULL) { + DCmdMark mark(dcmd); + return dcmd->_dcmdparser.num_arguments(); + } else { + return 0; + } +} +#endif // INCLUDE_SERVICES + ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") { @@ -406,7 +465,32 @@ JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated _jmxremote_ssl_config_file ("jmxremote.ssl.config.file", - "set com.sun.management.jmxremote.ssl_config_file", "STRING", false) + "set com.sun.management.jmxremote.ssl_config_file", "STRING", false), + +// JDP Protocol support + _jmxremote_autodiscovery + ("jmxremote.autodiscovery", + "set com.sun.management.jmxremote.autodiscovery", "STRING", false), + + _jdp_port + ("jdp.port", + "set com.sun.management.jdp.port", "INT", false), + + _jdp_address + ("jdp.address", + "set com.sun.management.jdp.address", "STRING", false), + + _jdp_source_addr + ("jdp.source_addr", + "set com.sun.management.jdp.source_addr", "STRING", false), + + _jdp_ttl + ("jdp.ttl", + "set com.sun.management.jdp.ttl", "INT", false), + + _jdp_pause + ("jdp.pause", + "set com.sun.management.jdp.pause", "INT", false) { _dcmdparser.add_dcmd_option(&_config_file); @@ -422,6 +506,12 @@ JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols); _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth); _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file); + _dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery); + _dcmdparser.add_dcmd_option(&_jdp_port); + _dcmdparser.add_dcmd_option(&_jdp_address); + _dcmdparser.add_dcmd_option(&_jdp_source_addr); + _dcmdparser.add_dcmd_option(&_jdp_ttl); + _dcmdparser.add_dcmd_option(&_jdp_pause); } @@ -436,7 +526,6 @@ int JMXStartRemoteDCmd::num_arguments() { } } - void JMXStartRemoteDCmd::execute(TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -466,7 +555,9 @@ void JMXStartRemoteDCmd::execute(TRAPS) { // file. #define PUT_OPTION(a) \ if ( (a).is_set() ){ \ - options.print("%scom.sun.management.%s=%s", comma, (a).name(), (a).value()); \ + options.print(\ + ( *((a).type()) == 'I' ) ? "%scom.sun.management.%s=%d" : "%scom.sun.management.%s=%s",\ + comma, (a).name(), (a).value()); \ comma[0] = ','; \ } @@ -483,6 +574,12 @@ void JMXStartRemoteDCmd::execute(TRAPS) { PUT_OPTION(_jmxremote_ssl_enabled_protocols); PUT_OPTION(_jmxremote_ssl_need_client_auth); PUT_OPTION(_jmxremote_ssl_config_file); + PUT_OPTION(_jmxremote_autodiscovery); + PUT_OPTION(_jdp_port); + PUT_OPTION(_jdp_address); + PUT_OPTION(_jdp_source_addr); + PUT_OPTION(_jdp_ttl); + PUT_OPTION(_jdp_pause); #undef PUT_OPTION diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 99d75a92f33..ac5d5809d1e 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -35,6 +35,7 @@ #include "services/diagnosticCommand.hpp" #include "services/diagnosticFramework.hpp" #include "services/diagnosticCommand_ext.hpp" +#include "utilities/macros.hpp" class HelpDCmd : public DCmdWithParser { protected: @@ -178,7 +179,7 @@ public: }; #endif // INCLUDE_SERVICES -// See also: inspeactheap in attachListener.cpp +// See also: inspectheap in attachListener.cpp class ClassHistogramDCmd : public DCmdWithParser { protected: DCmdArgument _all; @@ -197,6 +198,27 @@ public: virtual void execute(TRAPS); }; +class ClassStatsDCmd : public DCmdWithParser { +protected: + DCmdArgument _all; + DCmdArgument _csv; + DCmdArgument _help; + DCmdArgument _columns; +public: + ClassStatsDCmd(outputStream* output, bool heap); + static const char* name() { + return "GC.class_stats"; + } + static const char* description() { + return "Provide statistics about Java class meta data. Requires -XX:+UnlockDiagnosticVMOptions."; + } + static const char* impact() { + return "High: Depends on Java heap size and content."; + } + static int num_arguments(); + virtual void execute(TRAPS); +}; + // See also: thread_dump in attachListener.cpp class ThreadDumpDCmd : public DCmdWithParser { protected: @@ -236,6 +258,16 @@ class JMXStartRemoteDCmd : public DCmdWithParser { DCmdArgument _jmxremote_ssl_need_client_auth; DCmdArgument _jmxremote_ssl_config_file; + // JDP support + // Keep autodiscovery char* not bool to pass true/false + // as property value to java level. + DCmdArgument _jmxremote_autodiscovery; + DCmdArgument _jdp_port; + DCmdArgument _jdp_address; + DCmdArgument _jdp_source_addr; + DCmdArgument _jdp_ttl; + DCmdArgument _jdp_pause; + public: JMXStartRemoteDCmd(outputStream *output, bool heap_allocated); diff --git a/hotspot/src/share/vm/services/g1MemoryPool.hpp b/hotspot/src/share/vm/services/g1MemoryPool.hpp index c84ecb2d555..abe67e2f91c 100644 --- a/hotspot/src/share/vm/services/g1MemoryPool.hpp +++ b/hotspot/src/share/vm/services/g1MemoryPool.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_SERVICES_G1MEMORYPOOL_HPP #define SHARE_VM_SERVICES_G1MEMORYPOOL_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This file contains the three classes that represent the memory // pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index 0dbe2e86589..fa1bf273e07 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -40,9 +40,10 @@ #include "services/heapDumper.hpp" #include "services/threadService.hpp" #include "utilities/ostream.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS /* * HPROF binary format - description copied from: @@ -1866,7 +1867,7 @@ int HeapDumper::dump(const char* path) { if (error() == NULL) { char msg[256]; sprintf(msg, "Heap dump file created [%s bytes in %3.3f secs]", - os::jlong_format_specifier(), timer()->seconds()); + JLONG_FORMAT, timer()->seconds()); tty->print_cr(msg, writer.bytes_written()); } else { tty->print_cr("Dump file is incomplete: %s", writer.error()); diff --git a/hotspot/src/share/vm/services/lowMemoryDetector.cpp b/hotspot/src/share/vm/services/lowMemoryDetector.cpp index babd93ac85b..199a342dd77 100644 --- a/hotspot/src/share/vm/services/lowMemoryDetector.cpp +++ b/hotspot/src/share/vm/services/lowMemoryDetector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -353,7 +353,7 @@ void SensorInfo::clear(int count, TRAPS) { #ifndef PRODUCT void SensorInfo::print() { - tty->print_cr("%s count = %ld pending_triggers = %ld pending_clears = %ld", + tty->print_cr("%s count = " SIZE_FORMAT " pending_triggers = %ld pending_clears = %ld", (_sensor_on ? "on" : "off"), _sensor_count, _pending_trigger_count, _pending_clear_count); } diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp index a5b68d9b655..549622e9210 100644 --- a/hotspot/src/share/vm/services/management.cpp +++ b/hotspot/src/share/vm/services/management.cpp @@ -53,6 +53,7 @@ #include "services/memoryService.hpp" #include "services/runtimeService.hpp" #include "services/threadService.hpp" +#include "utilities/macros.hpp" PerfVariable* Management::_begin_vm_creation_time = NULL; PerfVariable* Management::_end_vm_creation_time = NULL; diff --git a/hotspot/src/share/vm/services/memBaseline.cpp b/hotspot/src/share/vm/services/memBaseline.cpp index 9d9832e8601..681b4d7d9d1 100644 --- a/hotspot/src/share/vm/services/memBaseline.cpp +++ b/hotspot/src/share/vm/services/memBaseline.cpp @@ -40,6 +40,7 @@ MemType2Name MemBaseline::MemType2NameMap[NUMBER_OF_MEMORY_TYPE] = { {mtNMT, "Memory Tracking"}, {mtChunk, "Pooled Free Chunks"}, {mtClassShared,"Shared spaces for classes"}, + {mtTest, "Test"}, {mtNone, "Unknown"} // It can happen when type tagging records are lagging // behind }; diff --git a/hotspot/src/share/vm/services/memPtr.cpp b/hotspot/src/share/vm/services/memPtr.cpp index 5d0fbf5bf57..3e124e2bde2 100644 --- a/hotspot/src/share/vm/services/memPtr.cpp +++ b/hotspot/src/share/vm/services/memPtr.cpp @@ -27,8 +27,8 @@ #include "services/memTracker.hpp" volatile jint SequenceGenerator::_seq_number = 1; +volatile unsigned long SequenceGenerator::_generation = 1; NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;) -DEBUG_ONLY(volatile unsigned long SequenceGenerator::_generation = 0;) jint SequenceGenerator::next() { jint seq = Atomic::add(1, &_seq_number); diff --git a/hotspot/src/share/vm/services/memPtr.hpp b/hotspot/src/share/vm/services/memPtr.hpp index a27c3eb4a10..e1c852ac7ba 100644 --- a/hotspot/src/share/vm/services/memPtr.hpp +++ b/hotspot/src/share/vm/services/memPtr.hpp @@ -47,16 +47,16 @@ class SequenceGenerator : AllStatic { static void reset() { assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); _seq_number = 1; - DEBUG_ONLY(_generation ++;) + _generation ++; }; - DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; }) + static unsigned long current_generation() { return _generation; } NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; }) private: - static volatile jint _seq_number; - NOT_PRODUCT(static jint _max_seq_number; ) - DEBUG_ONLY(static volatile unsigned long _generation; ) + static volatile jint _seq_number; + static volatile unsigned long _generation; + NOT_PRODUCT(static jint _max_seq_number; ) }; /* diff --git a/hotspot/src/share/vm/services/memRecorder.cpp b/hotspot/src/share/vm/services/memRecorder.cpp index 93703269ede..776ad223c00 100644 --- a/hotspot/src/share/vm/services/memRecorder.cpp +++ b/hotspot/src/share/vm/services/memRecorder.cpp @@ -55,7 +55,7 @@ volatile jint MemRecorder::_instance_count = 0; MemRecorder::MemRecorder() { assert(MemTracker::is_on(), "Native memory tracking is off"); Atomic::inc(&_instance_count); - debug_only(set_generation();) + set_generation(); if (MemTracker::track_callsite()) { _pointer_records = new (std::nothrow)FixedSizeMemPointerArray { // used for linked list MemRecorder* _next; // active recorder can only record a certain generation data - debug_only(unsigned long _generation;) + unsigned long _generation; protected: _NOINLINE_ MemRecorder(); @@ -251,6 +251,8 @@ class MemRecorder : public CHeapObj { SequencedRecordIterator pointer_itr(); + // return the generation of this recorder which it belongs to + unsigned long get_generation() const { return _generation; } protected: // number of MemRecorder instance static volatile jint _instance_count; @@ -263,7 +265,7 @@ class MemRecorder : public CHeapObj { static int sort_record_fn(const void* e1, const void* e2); debug_only(void check_dup_seq(jint seq) const;) - debug_only(void set_generation();) + void set_generation(); }; #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP diff --git a/hotspot/src/share/vm/services/memReporter.hpp b/hotspot/src/share/vm/services/memReporter.hpp index 38f1e60bd89..86d4b52efdf 100644 --- a/hotspot/src/share/vm/services/memReporter.hpp +++ b/hotspot/src/share/vm/services/memReporter.hpp @@ -29,6 +29,7 @@ #include "services/memBaseline.hpp" #include "services/memTracker.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" #if INCLUDE_NMT diff --git a/hotspot/src/share/vm/services/memTrackWorker.cpp b/hotspot/src/share/vm/services/memTrackWorker.cpp index 19b375d4085..8c38d1a3731 100644 --- a/hotspot/src/share/vm/services/memTrackWorker.cpp +++ b/hotspot/src/share/vm/services/memTrackWorker.cpp @@ -91,6 +91,8 @@ void MemTrackWorker::run() { MemSnapshot* snapshot = MemTracker::get_snapshot(); assert(snapshot != NULL, "Worker should not be started"); MemRecorder* rec; + unsigned long processing_generation = 0; + bool worker_idle = false; while (!MemTracker::shutdown_in_progress()) { NOT_PRODUCT(_last_gen_in_use = generations_in_use();) @@ -100,6 +102,12 @@ void MemTrackWorker::run() { rec = _gen[_head].next_recorder(); } if (rec != NULL) { + if (rec->get_generation() != processing_generation || worker_idle) { + processing_generation = rec->get_generation(); + worker_idle = false; + MemTracker::set_current_processing_generation(processing_generation); + } + // merge the recorder into staging area if (!snapshot->merge(rec)) { MemTracker::shutdown(MemTracker::NMT_out_of_memory); @@ -129,6 +137,9 @@ void MemTrackWorker::run() { MemTracker::shutdown(MemTracker::NMT_out_of_memory); } } else { + // worker thread is idle + worker_idle = true; + MemTracker::report_worker_idle(); snapshot->wait(1000); ThreadCritical tc; // check if more data arrived diff --git a/hotspot/src/share/vm/services/memTrackWorker.hpp b/hotspot/src/share/vm/services/memTrackWorker.hpp index 9a2d52802e2..be80e294d58 100644 --- a/hotspot/src/share/vm/services/memTrackWorker.hpp +++ b/hotspot/src/share/vm/services/memTrackWorker.hpp @@ -107,6 +107,7 @@ class MemTrackWorker : public NamedThread { NOT_PRODUCT(int _merge_count;) NOT_PRODUCT(int _last_gen_in_use;) + // how many generations are queued inline int generations_in_use() const { return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1)); } diff --git a/hotspot/src/share/vm/services/memTracker.cpp b/hotspot/src/share/vm/services/memTracker.cpp index c8032d8fd1a..4c110d584ac 100644 --- a/hotspot/src/share/vm/services/memTracker.cpp +++ b/hotspot/src/share/vm/services/memTracker.cpp @@ -29,6 +29,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/vm_operations.hpp" #include "services/memPtr.hpp" #include "services/memReporter.hpp" #include "services/memTracker.hpp" @@ -65,6 +66,8 @@ volatile MemTracker::NMTStates MemTracker::_state = NMT_uninited; MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none; int MemTracker::_thread_count = 255; volatile jint MemTracker::_pooled_recorder_count = 0; +volatile unsigned long MemTracker::_processing_generation = 0; +volatile bool MemTracker::_worker_thread_idle = false; debug_only(intx MemTracker::_main_thread_tid = 0;) NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) @@ -279,7 +282,7 @@ MemRecorder* MemTracker::get_new_or_pooled_instance() { } cur_head->set_next(NULL); Atomic::dec(&_pooled_recorder_count); - debug_only(cur_head->set_generation();) + cur_head->set_generation(); return cur_head; } } @@ -570,6 +573,51 @@ bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool sum return false; } +// Whitebox API for blocking until the current generation of NMT data has been merged +bool MemTracker::wbtest_wait_for_data_merge() { + // NMT can't be shutdown while we're holding _query_lock + MutexLockerEx lock(_query_lock, true); + assert(_worker_thread != NULL, "Invalid query"); + // the generation at query time, so NMT will spin till this generation is processed + unsigned long generation_at_query_time = SequenceGenerator::current_generation(); + unsigned long current_processing_generation = _processing_generation; + // if generation counter overflown + bool generation_overflown = (generation_at_query_time < current_processing_generation); + long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; + // spin + while (!shutdown_in_progress()) { + if (!generation_overflown) { + if (current_processing_generation > generation_at_query_time) { + return true; + } + } else { + assert(generations_to_wrap >= 0, "Sanity check"); + long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; + assert(current_generations_to_wrap >= 0, "Sanity check"); + // to overflow an unsigned long should take long time, so to_wrap check should be sufficient + if (current_generations_to_wrap > generations_to_wrap && + current_processing_generation > generation_at_query_time) { + return true; + } + } + + // if worker thread is idle, but generation is not advancing, that means + // there is not safepoint to let NMT advance generation, force one. + if (_worker_thread_idle) { + VM_ForceSafepoint vfs; + VMThread::execute(&vfs); + } + MemSnapshot* snapshot = get_snapshot(); + if (snapshot == NULL) { + return false; + } + snapshot->wait(1000); + current_processing_generation = _processing_generation; + } + // We end up here if NMT is shutting down before our data has been merged + return false; +} + // compare memory usage between current snapshot and baseline bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { MutexLockerEx lock(_query_lock, true); diff --git a/hotspot/src/share/vm/services/memTracker.hpp b/hotspot/src/share/vm/services/memTracker.hpp index 538195c0c75..764b2950543 100644 --- a/hotspot/src/share/vm/services/memTracker.hpp +++ b/hotspot/src/share/vm/services/memTracker.hpp @@ -91,9 +91,10 @@ class MemTracker : AllStatic { static bool compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only = true) { } + static bool wbtest_wait_for_data_merge() { } + static inline void sync() { } static inline void thread_exiting(JavaThread* thread) { } - }; @@ -111,6 +112,10 @@ class MemTracker : AllStatic { extern bool NMT_track_callsite; +#ifndef MAX_UNSIGNED_LONG +#define MAX_UNSIGNED_LONG (unsigned long)(-1) +#endif + #ifdef ASSERT #define DEBUG_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0) #else @@ -380,6 +385,11 @@ class MemTracker : AllStatic { static bool compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only = true); + // the version for whitebox testing support, it ensures that all memory + // activities before this method call, are reflected in the snapshot + // database. + static bool wbtest_wait_for_data_merge(); + // sync is called within global safepoint to synchronize nmt data static void sync(); @@ -432,6 +442,15 @@ class MemTracker : AllStatic { static void create_record_in_recorder(address addr, MEMFLAGS type, size_t size, address pc, JavaThread* thread); + static void set_current_processing_generation(unsigned long generation) { + _worker_thread_idle = false; + _processing_generation = generation; + } + + static void report_worker_idle() { + _worker_thread_idle = true; + } + private: // global memory snapshot static MemSnapshot* _snapshot; @@ -483,6 +502,11 @@ class MemTracker : AllStatic { static volatile enum NMTStates _state; // the reason for shutting down nmt static enum ShutdownReason _reason; + // the generation that NMT is processing + static volatile unsigned long _processing_generation; + // although NMT is still procesing current generation, but + // there is not more recorder to process, set idle state + static volatile bool _worker_thread_idle; }; #endif // !INCLUDE_NMT diff --git a/hotspot/src/share/vm/services/memoryPool.cpp b/hotspot/src/share/vm/services/memoryPool.cpp index dc608c49214..e2895b1f816 100644 --- a/hotspot/src/share/vm/services/memoryPool.cpp +++ b/hotspot/src/share/vm/services/memoryPool.cpp @@ -32,6 +32,7 @@ #include "services/management.hpp" #include "services/memoryManager.hpp" #include "services/memoryPool.hpp" +#include "utilities/macros.hpp" MemoryPool::MemoryPool(const char* name, PoolType type, @@ -208,7 +209,7 @@ MemoryUsage SurvivorContiguousSpacePool::get_memory_usage() { return MemoryUsage(initial_size(), used, committed, maxSize); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS CompactibleFreeListSpacePool::CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, const char* name, PoolType type, @@ -225,7 +226,7 @@ MemoryUsage CompactibleFreeListSpacePool::get_memory_usage() { return MemoryUsage(initial_size(), used, committed, maxSize); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS GenerationPool::GenerationPool(Generation* gen, const char* name, diff --git a/hotspot/src/share/vm/services/memoryPool.hpp b/hotspot/src/share/vm/services/memoryPool.hpp index c97fdbfa7b3..82606185340 100644 --- a/hotspot/src/share/vm/services/memoryPool.hpp +++ b/hotspot/src/share/vm/services/memoryPool.hpp @@ -30,9 +30,10 @@ #include "memory/heap.hpp" #include "memory/space.hpp" #include "services/memoryUsage.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A memory pool represents the memory area that the VM manages. // The Java virtual machine has at least one memory pool @@ -185,7 +186,7 @@ public: } }; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class CompactibleFreeListSpacePool : public CollectedMemoryPool { private: CompactibleFreeListSpace* _space; @@ -199,7 +200,7 @@ public: MemoryUsage get_memory_usage(); size_t used_in_bytes() { return _space->used(); } }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS class GenerationPool : public CollectedMemoryPool { diff --git a/hotspot/src/share/vm/services/memoryService.cpp b/hotspot/src/share/vm/services/memoryService.cpp index 03af9b99885..0040f9d96fc 100644 --- a/hotspot/src/share/vm/services/memoryService.cpp +++ b/hotspot/src/share/vm/services/memoryService.cpp @@ -43,7 +43,8 @@ #include "services/memoryPool.hpp" #include "services/memoryService.hpp" #include "utilities/growableArray.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/parNew/parNewGeneration.hpp" @@ -52,7 +53,7 @@ #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "services/g1MemoryPool.hpp" #include "services/psMemoryPool.hpp" -#endif +#endif // INCLUDE_ALL_GCS GrowableArray* MemoryService::_pools_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_pools_list_size, true); @@ -83,7 +84,7 @@ void MemoryService::set_universe_heap(CollectedHeap* heap) { add_gen_collected_heap_info(GenCollectedHeap::heap()); break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case CollectedHeap::ParallelScavengeHeap : { add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap()); break; @@ -92,7 +93,7 @@ void MemoryService::set_universe_heap(CollectedHeap* heap) { add_g1_heap_info(G1CollectedHeap::heap()); break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: { guarantee(false, "Unrecognized kind of heap"); } @@ -130,22 +131,22 @@ void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) { case Generation::DefNew: _minor_gc_manager = MemoryManager::get_copy_memory_manager(); break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: _minor_gc_manager = MemoryManager::get_parnew_memory_manager(); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: guarantee(false, "Unrecognized generation spec"); break; } if (policy->is_mark_sweep_policy()) { _major_gc_manager = MemoryManager::get_msc_memory_manager(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS } else if (policy->is_concurrent_mark_sweep_policy()) { _major_gc_manager = MemoryManager::get_cms_memory_manager(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { guarantee(false, "Unknown two-gen policy"); } @@ -159,7 +160,7 @@ void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) { add_generation_memory_pool(heap->get_gen(major), _major_gc_manager); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Add memory pools for ParallelScavengeHeap // This function currently only supports two generations collected heap. // The collector for ParallelScavengeHeap will have two memory managers. @@ -185,7 +186,7 @@ void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) { add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager); add_g1OldGen_memory_pool(g1h, _major_gc_manager); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS MemoryPool* MemoryService::add_gen(Generation* gen, const char* name, @@ -222,7 +223,7 @@ MemoryPool* MemoryService::add_survivor_spaces(DefNewGeneration* gen, return (MemoryPool*) pool; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space, const char* name, bool is_heap, @@ -233,7 +234,7 @@ MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space, _pools_list->append(pool); return (MemoryPool*) pool; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Add memory pool(s) for one generation void MemoryService::add_generation_memory_pool(Generation* gen, @@ -261,7 +262,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: { @@ -282,7 +283,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case Generation::MarkSweepCompact: { assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager"); @@ -293,7 +294,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ConcurrentMarkSweep: case Generation::ASConcurrentMarkSweep: { @@ -306,7 +307,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, true /* support_usage_threshold */); break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: assert(false, "should not reach here"); @@ -326,7 +327,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) { assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); @@ -384,7 +385,7 @@ void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h, mgr->add_pool(old_gen); _pools_list->append(old_gen); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void MemoryService::add_code_heap_memory_pool(CodeHeap* heap) { _code_heap_pool = new CodeHeapPool(heap, @@ -534,17 +535,17 @@ Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) { switch (kind) { case Generation::DefNew: -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS _fullGC=false; break; case Generation::MarkSweepCompact: -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ConcurrentMarkSweep: case Generation::ASConcurrentMarkSweep: -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS _fullGC=true; break; default: diff --git a/hotspot/src/share/vm/services/psMemoryPool.hpp b/hotspot/src/share/vm/services/psMemoryPool.hpp index 2fd193f70d0..080b49161f2 100644 --- a/hotspot/src/share/vm/services/psMemoryPool.hpp +++ b/hotspot/src/share/vm/services/psMemoryPool.hpp @@ -25,7 +25,8 @@ #ifndef SHARE_VM_SERVICES_PSMEMORYPOOL_HPP #define SHARE_VM_SERVICES_PSMEMORYPOOL_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/shared/mutableSpace.hpp" @@ -34,7 +35,7 @@ #include "memory/space.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -#endif +#endif // INCLUDE_ALL_GCS class PSGenerationPool : public CollectedMemoryPool { private: diff --git a/hotspot/src/share/vm/services/runtimeService.cpp b/hotspot/src/share/vm/services/runtimeService.cpp index bba6a95af73..49997dfc5b3 100644 --- a/hotspot/src/share/vm/services/runtimeService.cpp +++ b/hotspot/src/share/vm/services/runtimeService.cpp @@ -29,6 +29,7 @@ #include "services/runtimeService.hpp" #include "utilities/dtrace.hpp" #include "utilities/exceptions.hpp" +#include "utilities/macros.hpp" #ifndef USDT2 HS_DTRACE_PROBE_DECL(hs_private, safepoint__begin); diff --git a/hotspot/src/share/vm/shark/sharkBlock.cpp b/hotspot/src/share/vm/shark/sharkBlock.cpp index b4e98365efc..6b1b5fbe89c 100644 --- a/hotspot/src/share/vm/shark/sharkBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkBlock.cpp @@ -1032,7 +1032,7 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { check_null(value); object = value->generic_value(); } - if (is_get && field->is_constant()) { + if (is_get && field->is_constant() && field->is_static()) { SharkConstant *constant = SharkConstant::for_field(iter()); if (constant->is_loaded()) value = constant->value(builder()); @@ -1044,10 +1044,17 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { BasicType basic_type = field->type()->basic_type(); Type *stack_type = SharkType::to_stackType(basic_type); Type *field_type = SharkType::to_arrayType(basic_type); - + Type *type = field_type; + if (field->is_volatile()) { + if (field_type == SharkType::jfloat_type()) { + type = SharkType::jint_type(); + } else if (field_type == SharkType::jdouble_type()) { + type = SharkType::jlong_type(); + } + } Value *addr = builder()->CreateAddressOfStructEntry( object, in_ByteSize(field->offset_in_bytes()), - PointerType::getUnqual(field_type), + PointerType::getUnqual(type), "addr"); // Do the access @@ -1055,6 +1062,7 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { Value* field_value; if (field->is_volatile()) { field_value = builder()->CreateAtomicLoad(addr); + field_value = builder()->CreateBitCast(field_value, field_type); } else { field_value = builder()->CreateLoad(addr); } @@ -1074,6 +1082,7 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { } if (field->is_volatile()) { + field_value = builder()->CreateBitCast(field_value, type); builder()->CreateAtomicStore(field_value, addr); } else { builder()->CreateStore(field_value, addr); diff --git a/hotspot/src/share/vm/shark/sharkCompiler.cpp b/hotspot/src/share/vm/shark/sharkCompiler.cpp index 3438240ad00..cde6bc23e76 100644 --- a/hotspot/src/share/vm/shark/sharkCompiler.cpp +++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp @@ -185,6 +185,9 @@ void SharkCompiler::compile_method(ciEnv* env, // Build the LLVM IR for the method Function *function = SharkFunction::build(env, &builder, flow, name); + if (env->failing()) { + return; + } // Generate native code. It's unpleasant that we have to drop into // the VM to do this -- it blocks safepoints -- but I can't see any diff --git a/hotspot/src/share/vm/shark/sharkCompiler.hpp b/hotspot/src/share/vm/shark/sharkCompiler.hpp index 828a783a80d..7e530c142aa 100644 --- a/hotspot/src/share/vm/shark/sharkCompiler.hpp +++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp @@ -46,6 +46,9 @@ class SharkCompiler : public AbstractCompiler { // Missing feature tests bool supports_native() { return true; } bool supports_osr() { return true; } + bool can_compile_method(methodHandle method) { + return ! (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form()); + } // Customization bool needs_adapters() { return false; } diff --git a/hotspot/src/share/vm/shark/sharkConstant.cpp b/hotspot/src/share/vm/shark/sharkConstant.cpp index b45ec136e77..cd6e1152d0f 100644 --- a/hotspot/src/share/vm/shark/sharkConstant.cpp +++ b/hotspot/src/share/vm/shark/sharkConstant.cpp @@ -37,7 +37,12 @@ SharkConstant* SharkConstant::for_ldc(ciBytecodeStream *iter) { ciType *type = NULL; if (constant.basic_type() == T_OBJECT) { ciEnv *env = ciEnv::current(); - assert(constant.as_object()->klass() == env->String_klass() || constant.as_object()->klass() == env->Class_klass(), "should be"); + + assert(constant.as_object()->klass() == env->String_klass() + || constant.as_object()->klass() == env->Class_klass() + || constant.as_object()->klass()->is_subtype_of(env->MethodType_klass()) + || constant.as_object()->klass()->is_subtype_of(env->MethodHandle_klass()), "should be"); + type = constant.as_object()->klass(); } return new SharkConstant(constant, type); diff --git a/hotspot/src/share/vm/shark/sharkFunction.cpp b/hotspot/src/share/vm/shark/sharkFunction.cpp index 917ed0109ac..1ec7a371fb4 100644 --- a/hotspot/src/share/vm/shark/sharkFunction.cpp +++ b/hotspot/src/share/vm/shark/sharkFunction.cpp @@ -77,6 +77,10 @@ void SharkFunction::initialize(const char *name) { // Walk the tree from the start block to determine which // blocks are entered and which blocks require phis SharkTopLevelBlock *start_block = block(flow()->start_block_num()); + if (is_osr() && start_block->stack_depth_at_entry() != 0) { + env()->record_method_not_compilable("can't compile OSR block with incoming stack-depth > 0"); + return; + } assert(start_block->start() == flow()->start_bci(), "blocks out of order"); start_block->enter(); diff --git a/hotspot/src/share/vm/shark/sharkInliner.cpp b/hotspot/src/share/vm/shark/sharkInliner.cpp index c9e895a9c9b..1f4ea829fb3 100644 --- a/hotspot/src/share/vm/shark/sharkInliner.cpp +++ b/hotspot/src/share/vm/shark/sharkInliner.cpp @@ -725,7 +725,7 @@ bool SharkInlinerHelper::do_field_access(bool is_get, bool is_field) { // Push the result if necessary if (is_get) { bool result_pushed = false; - if (field->is_constant()) { + if (field->is_constant() && field->is_static()) { SharkConstant *sc = SharkConstant::for_field(iter()); if (sc->is_loaded()) { push(sc->is_nonzero()); diff --git a/hotspot/src/share/vm/shark/sharkInvariants.hpp b/hotspot/src/share/vm/shark/sharkInvariants.hpp index 50e1be8ea6d..e6b6399fe26 100644 --- a/hotspot/src/share/vm/shark/sharkInvariants.hpp +++ b/hotspot/src/share/vm/shark/sharkInvariants.hpp @@ -68,7 +68,7 @@ class SharkCompileInvariants : public ResourceObj { // // Accessing this directly is kind of ugly, so it's private. Add // new accessors below if you need something from it. - private: + protected: ciEnv* env() const { assert(_env != NULL, "env not available"); return _env; @@ -99,13 +99,15 @@ class SharkCompileInvariants : public ResourceObj { DebugInformationRecorder* debug_info() const { return env()->debug_info(); } - Dependencies* dependencies() const { - return env()->dependencies(); - } SharkCodeBuffer* code_buffer() const { return builder()->code_buffer(); } + public: + Dependencies* dependencies() const { + return env()->dependencies(); + } + // Commonly used classes protected: ciInstanceKlass* java_lang_Object_klass() const { diff --git a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp index fcd6906caad..6614146bb42 100644 --- a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp @@ -113,7 +113,19 @@ void SharkTopLevelBlock::scan_for_traps() { ciSignature* sig; method = iter()->get_method(will_link, &sig); assert(will_link, "typeflow responsibility"); - + // We can't compile calls to method handle intrinsics, because we use + // the interpreter entry points and they expect the top frame to be an + // interpreter frame. We need to implement the intrinsics for Shark. + if (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form()) { + if (SharkPerformanceWarnings) { + warning("JSR292 optimization not yet implemented in Shark"); + } + set_trap( + Deoptimization::make_trap_request( + Deoptimization::Reason_unhandled, + Deoptimization::Action_make_not_compilable), bci()); + return; + } if (!method->holder()->is_linked()) { set_trap( Deoptimization::make_trap_request( @@ -158,6 +170,16 @@ void SharkTopLevelBlock::scan_for_traps() { return; } break; + case Bytecodes::_invokedynamic: + case Bytecodes::_invokehandle: + if (SharkPerformanceWarnings) { + warning("JSR292 optimization not yet implemented in Shark"); + } + set_trap( + Deoptimization::make_trap_request( + Deoptimization::Reason_unhandled, + Deoptimization::Action_make_not_compilable), bci()); + return; } } @@ -1030,7 +1052,6 @@ ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller, dest_method->holder() == java_lang_Object_klass()) return dest_method; -#ifdef SHARK_CAN_DEOPTIMIZE_ANYWHERE // This code can replace a virtual call with a direct call if this // class is the only one in the entire set of loaded classes that // implements this method. This makes the compiled code dependent @@ -1064,6 +1085,8 @@ ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller, if (monomorphic_target != NULL) { assert(!monomorphic_target->is_abstract(), "shouldn't be"); + function()->dependencies()->assert_unique_concrete_method(actual_receiver, monomorphic_target); + // Opto has a bunch of type checking here that I don't // understand. It's to inhibit casting in one direction, // possibly because objects in Opto can have inexact @@ -1097,7 +1120,6 @@ ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller, // with non-monomorphic targets if the receiver has an exact // type. We don't mark types this way, so we can't do this. -#endif // SHARK_CAN_DEOPTIMIZE_ANYWHERE return NULL; } @@ -1298,8 +1320,9 @@ void SharkTopLevelBlock::do_call() { // Try to inline the call if (!call_is_virtual) { - if (SharkInliner::attempt_inline(call_method, current_state())) + if (SharkInliner::attempt_inline(call_method, current_state())) { return; + } } // Find the method we are calling diff --git a/hotspot/src/share/vm/utilities/exceptions.hpp b/hotspot/src/share/vm/utilities/exceptions.hpp index 740912d3909..089cd3e0811 100644 --- a/hotspot/src/share/vm/utilities/exceptions.hpp +++ b/hotspot/src/share/vm/utilities/exceptions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -267,6 +267,7 @@ class Exceptions { #define THROW_WRAPPED_0(name, oop_to_wrap) THROW_WRAPPED_(name, oop_to_wrap, 0) #define THROW_ARG_0(name, signature, arg) THROW_ARG_(name, signature, arg, 0) #define THROW_MSG_CAUSE_0(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, 0) +#define THROW_MSG_CAUSE_NULL(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, NULL) #define THROW_NULL(name) THROW_(name, NULL) #define THROW_MSG_NULL(name, message) THROW_MSG_(name, message, NULL) diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index e00be90320e..5c10cf018be 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1250,6 +1250,14 @@ inline int build_int_from_shorts( jushort low, jushort high ) { #define PTR64_FORMAT "0x%016" PRIx64 +// Format jlong, if necessary +#ifndef JLONG_FORMAT +#define JLONG_FORMAT INT64_FORMAT +#endif +#ifndef JULONG_FORMAT +#define JULONG_FORMAT UINT64_FORMAT +#endif + // Format pointers which change size between 32- and 64-bit. #ifdef _LP64 #define INTPTR_FORMAT "0x%016" PRIxPTR diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp index e103816de93..a69708f8c8f 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -306,4 +306,8 @@ inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } #endif #define offsetof(klass,field) offset_of(klass,field) +#if defined(_LP64) && defined(__APPLE__) +#define JLONG_FORMAT "%ld" +#endif // _LP64 && __APPLE__ + #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_GCC_HPP diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index 64e331d90b0..a97e9e7d039 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -130,23 +130,23 @@ #endif // INCLUDE_MANAGEMENT /* - * When INCLUDE_ALTERNATE_GCS is false the only garbage collectors + * When INCLUDE_ALL_GCS is false the only garbage collectors * included in the JVM are defaultNewGeneration and markCompact. * - * When INCLUDE_ALTERNATE_GCS is true all garbage collectors are + * When INCLUDE_ALL_GCS is true all garbage collectors are * included in the JVM. */ -#ifndef INCLUDE_ALTERNATE_GCS -#define INCLUDE_ALTERNATE_GCS 1 -#endif // INCLUDE_ALTERNATE_GCS +#ifndef INCLUDE_ALL_GCS +#define INCLUDE_ALL_GCS 1 +#endif // INCLUDE_ALL_GCS -#if INCLUDE_ALTERNATE_GCS -#define NOT_ALTERNATE_GCS_RETURN /* next token must be ; */ -#define NOT_ALTERNATE_GCS_RETURN_(code) /* next token must be ; */ +#if INCLUDE_ALL_GCS +#define NOT_ALL_GCS_RETURN /* next token must be ; */ +#define NOT_ALL_GCS_RETURN_(code) /* next token must be ; */ #else -#define NOT_ALTERNATE_GCS_RETURN {} -#define NOT_ALTERNATE_GCS_RETURN_(code) { return code; } -#endif // INCLUDE_ALTERNATE_GCS +#define NOT_ALL_GCS_RETURN {} +#define NOT_ALL_GCS_RETURN_(code) { return code; } +#endif // INCLUDE_ALL_GCS #ifndef INCLUDE_NMT #define INCLUDE_NMT 1 diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 2b6e2eeb853..ea0a0c25bec 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,13 +243,11 @@ outputStream& outputStream::indent() { } void outputStream::print_jlong(jlong value) { - // N.B. Same as INT64_FORMAT - print(os::jlong_format_specifier(), value); + print(JLONG_FORMAT, value); } void outputStream::print_julong(julong value) { - // N.B. Same as UINT64_FORMAT - print(os::julong_format_specifier(), value); + print(JULONG_FORMAT, value); } /** diff --git a/hotspot/src/share/vm/utilities/taskqueue.cpp b/hotspot/src/share/vm/utilities/taskqueue.cpp index fbb035adf0c..862c9b304fb 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.cpp +++ b/hotspot/src/share/vm/utilities/taskqueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -239,8 +239,8 @@ ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { #ifdef TRACESPINNING void ParallelTaskTerminator::print_termination_counts() { - gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %lld " - "Total spins: %lld Total peeks: %lld", + gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: " UINT32_FORMAT + " Total spins: " UINT32_FORMAT " Total peeks: " UINT32_FORMAT, total_yields(), total_spins(), total_peeks()); diff --git a/hotspot/src/share/vm/utilities/top.hpp b/hotspot/src/share/vm/utilities/top.hpp index 034148a50db..b1abbc2f6a5 100644 --- a/hotspot/src/share/vm/utilities/top.hpp +++ b/hotspot/src/share/vm/utilities/top.hpp @@ -33,9 +33,9 @@ #include "utilities/macros.hpp" #include "utilities/ostream.hpp" #include "utilities/sizes.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_globals.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index ddb6e1cf882..d8fe93b64f3 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -702,7 +702,7 @@ void VMError::report(outputStream* st) { if (_verbose && Universe::is_fully_initialized()) { // print code cache information before vm abort - CodeCache::print_bounds(st); + CodeCache::print_summary(st); st->cr(); } diff --git a/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp b/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp index 7e594232af4..e344aea4bbf 100644 --- a/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp +++ b/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp @@ -23,9 +23,10 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "utilities/yieldingWorkgroup.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Forward declaration of classes declared here. diff --git a/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp b/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp index f9646f91f7f..5a626ce7fa3 100644 --- a/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp +++ b/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP #define SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "utilities/workgroup.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Forward declarations diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile index c8efce4276c..7bd42a1e28a 100644 --- a/hotspot/test/Makefile +++ b/hotspot/test/Makefile @@ -189,9 +189,9 @@ jtreg_tests: prep $(JT_HOME) $(PRODUCT_HOME) $(JTREG) $(JTREG) -a -v:fail,error \ $(JTREG_KEY_OPTION) \ $(EXTRA_JTREG_OPTIONS) \ - -r:$(ABS_TEST_OUTPUT_DIR)/JTreport \ - -w:$(ABS_TEST_OUTPUT_DIR)/JTwork \ - -jdk:$(PRODUCT_HOME) \ + -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \ + -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork \ + -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \ $(JAVA_OPTIONS:%=-vmoption:%) \ $(JTREG_TESTDIRS) \ || $(BUNDLE_UP_FAILED) diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index 24014f68209..629bb54ddb4 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -28,4 +28,4 @@ # DO NOT EDIT without first contacting hotspot-regtest@sun.com # The list of keywords supported in this test suite -keys=cte_test +keys=cte_test jcmd nmt regression diff --git a/hotspot/test/compiler/6896617/Test6896617.java b/hotspot/test/compiler/6896617/Test6896617.java new file mode 100644 index 00000000000..e28d3d7d57b --- /dev/null +++ b/hotspot/test/compiler/6896617/Test6896617.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 6896617 + * @summary Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() with SSE instructions on x86 + * @run main/othervm/timeout=1200 -Xbatch -Xmx256m Test6896617 + * + */ + +import java.util.*; +import java.nio.*; +import java.nio.charset.*; + +public class Test6896617 { + final static int SIZE = 256; + + public static void main(String[] args) { + String csn = "ISO-8859-1"; + Charset cs = Charset.forName(csn); + CharsetEncoder enc = cs.newEncoder(); + enc.onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + CharsetDecoder dec = cs.newDecoder(); + dec.onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + + byte repl = (byte)'?'; + enc.replaceWith(new byte[] { repl }); + + // Use internal API for tests. + sun.nio.cs.ArrayEncoder arrenc = (sun.nio.cs.ArrayEncoder)enc; + sun.nio.cs.ArrayDecoder arrdec = (sun.nio.cs.ArrayDecoder)dec; + + // Populate char[] with chars which can be encoded by ISO_8859_1 (<= 0xFF) + Random rnd = new Random(0); + int maxchar = 0xFF; + char[] a = new char[SIZE]; + byte[] b = new byte[SIZE]; + char[] at = new char[SIZE]; + byte[] bt = new byte[SIZE]; + for (int i = 0; i < SIZE; i++) { + char c = (char) rnd.nextInt(maxchar); + if (!enc.canEncode(c)) { + System.out.printf("Something wrong: can't encode c=%03x\n", (int)c); + System.exit(97); + } + a[i] = c; + b[i] = (byte)c; + at[i] = (char)-1; + bt[i] = (byte)-1; + } + if (arrenc.encode(a, 0, SIZE, bt) != SIZE || !Arrays.equals(b, bt)) { + System.out.println("Something wrong: ArrayEncoder.encode failed"); + System.exit(97); + } + if (arrdec.decode(b, 0, SIZE, at) != SIZE || !Arrays.equals(a, at)) { + System.out.println("Something wrong: ArrayDecoder.decode failed"); + System.exit(97); + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + + ByteBuffer bb = ByteBuffer.wrap(b); + CharBuffer ba = CharBuffer.wrap(a); + ByteBuffer bbt = ByteBuffer.wrap(bt); + CharBuffer bat = CharBuffer.wrap(at); + if (!enc.encode(ba, bbt, true).isUnderflow() || !Arrays.equals(b, bt)) { + System.out.println("Something wrong: Encoder.encode failed"); + System.exit(97); + } + if (!dec.decode(bb, bat, true).isUnderflow() || !Arrays.equals(a, at)) { + System.out.println("Something wrong: Decoder.decode failed"); + System.exit(97); + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + + // Warm up + boolean failed = false; + int result = 0; + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, SIZE, bt); + result -= arrdec.decode(b, 0, SIZE, at); + } + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, SIZE, bt); + result -= arrdec.decode(b, 0, SIZE, at); + } + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, SIZE, bt); + result -= arrdec.decode(b, 0, SIZE, at); + } + if (result != 0 || !Arrays.equals(b, bt) || !Arrays.equals(a, at)) { + failed = true; + System.out.println("Failed: ArrayEncoder.encode char[" + SIZE + "] and ArrayDecoder.decode byte[" + SIZE + "]"); + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + + boolean is_underflow = true; + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); bat.clear(); bbt.clear(); + boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); + boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); + is_underflow = is_underflow && enc_res && dec_res; + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); bat.clear(); bbt.clear(); + boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); + boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); + is_underflow = is_underflow && enc_res && dec_res; + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); bat.clear(); bbt.clear(); + boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); + boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); + is_underflow = is_underflow && enc_res && dec_res; + } + if (!is_underflow || !Arrays.equals(b, bt) || !Arrays.equals(a, at)) { + failed = true; + System.out.println("Failed: Encoder.encode char[" + SIZE + "] and Decoder.decode byte[" + SIZE + "]"); + } + + // Test encoder with different source and destination sizes + System.out.println("Testing different source and destination sizes"); + for (int i = 1; i <= SIZE; i++) { + for (int j = 1; j <= SIZE; j++) { + bt = new byte[j]; + // very source's SIZE + result = arrenc.encode(a, 0, i, bt); + int l = Math.min(i, j); + if (result != l) { + failed = true; + System.out.println("Failed: encode char[" + i + "] to byte[" + j + "]: result = " + result + ", expected " + l); + } + for (int k = 0; k < l; k++) { + if (bt[k] != b[k]) { + failed = true; + System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[k]); + } + } + // very source's offset + int sz = SIZE - i + 1; + result = arrenc.encode(a, i-1, sz, bt); + l = Math.min(sz, j); + if (result != l) { + failed = true; + System.out.println("Failed: encode char[" + sz + "] to byte[" + j + "]: result = " + result + ", expected " + l); + } + for (int k = 0; k < l; k++) { + if (bt[k] != b[i+k-1]) { + failed = true; + System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[i+k-1]); + } + } + } + } + + // Test encoder with char > 0xFF + System.out.println("Testing big char"); + + byte orig = (byte)'A'; + bt = new byte[SIZE]; + for (int i = 1; i <= SIZE; i++) { + for (int j = 0; j < i; j++) { + a[j] += 0x100; + // make sure to replace a different byte + bt[j] = orig; + result = arrenc.encode(a, 0, i, bt); + if (result != i) { + failed = true; + System.out.println("Failed: encode char[" + i + "] to byte[" + i + "]: result = " + result + ", expected " + i); + } + if (bt[j] != repl) { + failed = true; + System.out.println("Failed: encoded replace byte[" + j + "] (" + bt[j] + ") != " + repl); + } + bt[j] = b[j]; // Restore to compare whole array + for (int k = 0; k < i; k++) { + if (bt[k] != b[k]) { + failed = true; + System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[k]); + } + } + a[j] -= 0x100; // Restore + } + } + + // Test sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() performance. + + int itrs = Integer.getInteger("iterations", 1000000); + int size = Integer.getInteger("size", 256); + a = new char[size]; + b = new byte[size]; + bt = new byte[size]; + for (int i = 0; i < size; i++) { + char c = (char) rnd.nextInt(maxchar); + if (!enc.canEncode(c)) { + System.out.printf("Something wrong: can't encode c=%03x\n", (int)c); + System.exit(97); + } + a[i] = c; + b[i] = (byte)-1; + bt[i] = (byte)c; + } + ba = CharBuffer.wrap(a); + bb = ByteBuffer.wrap(b); + boolean enc_res = enc.encode(ba, bb, true).isUnderflow(); + if (!enc_res || !Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 1: Encoder.encode char[" + size + "]"); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + + // Make sure to recompile method if needed before performance run. + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); + enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); + enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); + } + if (!enc_res || !Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 2: Encoder.encode char[" + size + "]"); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + + System.out.println("Testing ISO_8859_1$Encode.encodeArrayLoop() performance"); + long start = System.currentTimeMillis(); + for (int i = 0; i < itrs; i++) { + ba.clear(); bb.clear(); + enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); + } + long end = System.currentTimeMillis(); + if (!enc_res || !Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 3: Encoder.encode char[" + size + "]"); + } else { + System.out.println("size: " + size + " time: " + (end - start)); + } + + // Test sun.nio.cs.ISO_8859_1$Encode.encode() performance. + + // Make sure to recompile method if needed before performance run. + result = 0; + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, size, b); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, size, b); + } + if (result != size*20000 || !Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 1: ArrayEncoder.encode char[" + SIZE + "]"); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + + System.out.println("Testing ISO_8859_1$Encode.encode() performance"); + result = 0; + start = System.currentTimeMillis(); + for (int i = 0; i < itrs; i++) { + result += arrenc.encode(a, 0, size, b); + } + end = System.currentTimeMillis(); + if (!Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 2: ArrayEncoder.encode char[" + size + "]"); + } else { + System.out.println("size: " + size + " time: " + (end - start)); + } + + if (failed) { + System.out.println("FAILED"); + System.exit(97); + } + System.out.println("PASSED"); + } +} diff --git a/hotspot/test/compiler/7190310/Test7190310.java b/hotspot/test/compiler/7190310/Test7190310.java index 57a89b93b39..b45c60bf196 100644 --- a/hotspot/test/compiler/7190310/Test7190310.java +++ b/hotspot/test/compiler/7190310/Test7190310.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -23,7 +23,16 @@ */ /* - * Manual test + * @test + * @bug 7190310 + * @summary Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops + * @run main/othervm/timeout=600 -Xbatch Test7190310 + */ + +/* + * Note bug exhibits as infinite loop, timeout is helpful. + * It should normally finish pretty quickly, but on some especially slow machines + * it may not. The companion _unsafe test lacks a timeout, but that is okay. */ import java.lang.ref.*; diff --git a/hotspot/test/compiler/8004741/Test8004741.java b/hotspot/test/compiler/8004741/Test8004741.java index 95e63b9c0c1..baacc34763d 100644 --- a/hotspot/test/compiler/8004741/Test8004741.java +++ b/hotspot/test/compiler/8004741/Test8004741.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -25,70 +25,160 @@ * @test Test8004741.java * @bug 8004741 * @summary Missing compiled exception handle table entry for multidimensional array allocation + * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers -XX:+SafepointALot -XX:GuaranteedSafepointInterval=100 Test8004741 * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers Test8004741 - * */ import java.util.*; public class Test8004741 extends Thread { + static int passed = 0; + + /** + * Loop forever allocating 2-d arrays. + * Catches and rethrows all exceptions; in the case of ThreadDeath, increments passed. + * Note that passed is incremented here because this is the exception handler with + * the smallest scope; we only want to declare success in the case where it is highly + * likely that the test condition + * (exception in 2-d array alloc interrupted by ThreadDeath) + * actually occurs. + */ static int[][] test(int a, int b) throws Exception { - int[][] ar = null; + int[][] ar; try { ar = new int[a][b]; - } catch (Error e) { - System.out.println("test got Error"); - passed = true; - throw(e); - } catch (Exception e) { - System.out.println("test got Exception"); + } catch (ThreadDeath e) { + System.out.println("test got ThreadDeath"); + passed++; throw(e); } return ar; } - static boolean passed = false; + /* Cookbook wait-notify to track progress of test thread. */ + Object progressLock = new Object(); + private static final int NOT_STARTED = 0; + private static final int RUNNING = 1; + private static final int STOPPING = 2; - public void run() { - System.out.println("test started"); - try { - while(true) { - test(2,20000); + int progressState = NOT_STARTED; + + void toState(int state) { + synchronized (progressLock) { + progressState = state; + progressLock.notify(); + } + } + + void waitFor(int state) { + synchronized (progressLock) { + while (progressState < state) { + try { + progressLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + System.out.println("unexpected InterruptedException"); + fail(); } - } catch (ThreadDeath e) { - System.out.println("test got ThreadDeath"); - passed = true; - } catch (Error e) { - e.printStackTrace(); - System.out.println("test got Error"); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("test got Exception"); } + if (progressState > state) { + System.out.println("unexpected test state change, expected " + + state + " but saw " + progressState); + fail(); + } + } + } + + /** + * Loops running test until some sort of an exception or error, + * expects to see ThreadDeath. + */ + public void run() { + try { + // Print before state change, so that other thread is most likely + // to see this thread executing calls to test() in a loop. + System.out.println("thread running"); + toState(RUNNING); + while (true) { + // (2,2) (2,10) (2,100) were observed to tickle the bug; + test(2, 100); + } + } catch (ThreadDeath e) { + // nothing to say, passing was incremented by the test. + } catch (Throwable e) { + e.printStackTrace(); + System.out.println("unexpected Throwable " + e); + fail(); + } + toState(STOPPING); + } + + /** + * Runs a single trial of the test in a thread. + * No single trial is definitive, since the ThreadDeath + * exception might not land in the tested region of code. + */ + public static void threadTest() throws InterruptedException { + Test8004741 t = new Test8004741(); + t.start(); + t.waitFor(RUNNING); + Thread.sleep(100); + System.out.println("stopping thread"); + t.stop(); + t.waitFor(STOPPING); + t.join(); } public static void main(String[] args) throws Exception { + // Warm up "test" + // t will never be started. for (int n = 0; n < 11000; n++) { - test(2, 20); + test(2, 100); } - // First test exception catch - Test8004741 t = new Test8004741(); + // Will this sleep help ensure that the compiler is run? + Thread.sleep(500); + passed = 0; - passed = false; - t.start(); - Thread.sleep(1000); - t.stop(); + try { + test(-1, 100); + System.out.println("Missing NegativeArraySizeException #1"); + fail(); + } catch ( java.lang.NegativeArraySizeException e ) { + System.out.println("Saw expected NegativeArraySizeException #1"); + } - Thread.sleep(5000); - t.join(); - if (passed) { + try { + test(100, -1); + fail(); + System.out.println("Missing NegativeArraySizeException #2"); + fail(); + } catch ( java.lang.NegativeArraySizeException e ) { + System.out.println("Saw expected NegativeArraySizeException #2"); + } + + /* Test repetitions. If the test succeeds-mostly, it succeeds, + * as long as it does not crash (the outcome if the exception range + * table entry for the array allocation is missing). + */ + int N = 12; + for (int n = 0; n < N; n++) { + threadTest(); + } + + if (passed > N/2) { + System.out.println("Saw " + passed + " out of " + N + " possible ThreadDeath hits"); System.out.println("PASSED"); } else { - System.out.println("FAILED"); - System.exit(97); + System.out.println("Too few ThreadDeath hits; expected at least " + N/2 + + " but saw only " + passed); + fail(); } } + static void fail() { + System.out.println("FAILED"); + System.exit(97); + } }; diff --git a/hotspot/test/runtime/7158988/FieldMonitor.java b/hotspot/test/runtime/7158988/FieldMonitor.java index 584d39d20ca..5421f626278 100644 --- a/hotspot/test/runtime/7158988/FieldMonitor.java +++ b/hotspot/test/runtime/7158988/FieldMonitor.java @@ -24,8 +24,10 @@ /* * @test FieldMonitor.java * @bug 7158988 + * @key regression * @summary verify jvm does not crash while debugging - * @run shell TestFieldMonitor.sh + * @run compile TestPostFieldModification.java + * @run main/othervm FieldMonitor * @author axel.siebenborn@sap.com */ import java.io.BufferedReader; diff --git a/hotspot/test/runtime/7158988/TestFieldMonitor.sh b/hotspot/test/runtime/7158988/TestFieldMonitor.sh deleted file mode 100644 index aa18c1609ba..00000000000 --- a/hotspot/test/runtime/7158988/TestFieldMonitor.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh - -if [ "${TESTSRC}" = "" ] -then TESTSRC=. -fi - -if [ "${TESTJAVA}" = "" ] -then - PARENT=`dirname \`which java\`` - TESTJAVA=`dirname ${PARENT}` - echo "TESTJAVA not set, selecting " ${TESTJAVA} - echo "If this is incorrect, try setting the variable manually." -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin) - NULL=/dev/null - PS=":" - FS="/" - ;; - Windows_95 | Windows_98 | Windows_ME ) - NULL=NUL - PS=";" - FS="\\" - echo "Test skipped, only for WinNT" - exit 0 - ;; - Windows_NT ) - NULL=NUL - PS=";" - FS="\\" - ;; - CYGWIN_NT* ) - NULL=/dev/null - PS=";" - FS="/" - ;; - CYGWIN_* ) - NULL=/dev/null - PS=";" - FS="/" - echo "Test skipped, only for WinNT" - exit 0 - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH - -cp ${TESTSRC}${FS}*.java . - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion - -${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out - -grep "A fatal error has been detected" test.out > ${NULL} -if [ $? = 0 ]; then - cat test.out - STATUS=1 -fi - -exit $STATUS diff --git a/hotspot/test/runtime/8000968/Test8000968.sh b/hotspot/test/runtime/8000968/Test8000968.sh new file mode 100644 index 00000000000..cd7183476cf --- /dev/null +++ b/hotspot/test/runtime/8000968/Test8000968.sh @@ -0,0 +1,99 @@ +# +# Copyright (c) 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. +# + + +# @test Test8000968.sh +# @bug 8000968 +# @summary NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes=32 +# @run shell Test8000968.sh +# + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + printf "TESTJAVA not set, selecting " ${TESTJAVA} + printf " If this is incorrect, try setting the variable manually.\n" +fi + + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* ) + FS="\\" + NULL=NUL + ;; + * ) + FS="/" + NULL=/dev/null + ;; +esac + +JAVA=${TESTJAVA}${FS}bin${FS}java + +# +# See if platform has 64 bit java. +# +${JAVA} ${TESTVMOPTS} -d64 -version 2>&1 | grep -i "does not support" > ${NULL} +if [ "$?" != "1" ] +then + printf "Platform is 32 bit, does not support -XX:ObjectAlignmentInBytes= option.\n" + printf "Passed.\n" + exit 0 +fi + +# +# Test -XX:ObjectAlignmentInBytes with -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops. +# +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=16 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=16 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=32 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=32 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=64 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=64 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=128 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=128 option did not work.\n" + exit 1 +fi + + +printf "Passed.\n" +exit 0 diff --git a/hotspot/test/runtime/8007475/StackMapFrameTest.java b/hotspot/test/runtime/8007475/StackMapFrameTest.java new file mode 100644 index 00000000000..b927ae76db6 --- /dev/null +++ b/hotspot/test/runtime/8007475/StackMapFrameTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8007475 + * @summary Test memory stomp in stack map test + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMallocOnly StackMapFrameTest + */ +public class StackMapFrameTest { + + public static void foo() { + Object o = new Object(); + } + + public static void main(String args[]) { + for (int i = 0; i < 25000; i++) { + foo(); + } + } +} diff --git a/hotspot/test/runtime/NMT/AllocTestType.java b/hotspot/test/runtime/NMT/AllocTestType.java new file mode 100644 index 00000000000..7644884445d --- /dev/null +++ b/hotspot/test/runtime/NMT/AllocTestType.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd + * @key nmt jcmd + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI AllocTestType.java + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class AllocTestType { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Use WB API to alloc with the mtTest type + if (!WhiteBox.getWhiteBox().NMTAllocTest()) { + throw new Exception("Call to WB API NMTAllocTest() failed"); + } + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=512KB)"); + + // Free the memory allocated by NMTAllocTest + if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) { + throw new Exception("Call to WB API NMTFreeTestMemory() failed"); + } + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff --git a/hotspot/test/runtime/NMT/BaselineWithParameter.java b/hotspot/test/runtime/NMT/BaselineWithParameter.java new file mode 100644 index 00000000000..594bd7165ed --- /dev/null +++ b/hotspot/test/runtime/NMT/BaselineWithParameter.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8004802 + * @key nmt jcmd regression + * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter + */ + +import com.oracle.java.testlibrary.*; + +public class BaselineWithParameter { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory baseline=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"}); + pb.start(); + + // Run 'jcmd VM.native_memory summary=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("No command to execute"); + + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineDetail.java b/hotspot/test/runtime/NMT/CommandLineDetail.java new file mode 100644 index 00000000000..d993316ba9c --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineDetail.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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. + */ + + /* + * @test + * @key nmt + * @summary Running with NMT detail should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineDetail { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=detail", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java new file mode 100644 index 00000000000..956cdd26006 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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. + */ + + /* + * @test + * @key nmt + * @summary Empty argument to NMT should result in an informative error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineEmptyArgument { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking="); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]"); + output.shouldHaveExitValue(1); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java new file mode 100644 index 00000000000..79cc2de9442 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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. + */ + + /* + * @test + * @key nmt + * @summary Invalid argument to NMT should result in an informative error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineInvalidArgument { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking=apa"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]"); + output.shouldHaveExitValue(1); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineSummary.java b/hotspot/test/runtime/NMT/CommandLineSummary.java new file mode 100644 index 00000000000..b8415d1bde9 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineSummary.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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. + */ + + /* + * @test + * @key nmt + * @summary Running with NMT summary should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineSummary { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=summary", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java new file mode 100644 index 00000000000..e8d950cba0a --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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. + */ + + /* + * @test + * @key nmt + * @summary Turning off NMT should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineTurnOffNMT { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=off", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/JcmdScale.java b/hotspot/test/runtime/NMT/JcmdScale.java new file mode 100644 index 00000000000..e57d27b59a3 --- /dev/null +++ b/hotspot/test/runtime/NMT/JcmdScale.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Test the NMT scale parameter + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdScale { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("KB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("MB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + } +} diff --git a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java new file mode 100644 index 00000000000..7b58a841315 --- /dev/null +++ b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that NMT is not enabled + * @library /testlibrary + * First run without enabling NMT + * @run main/othervm JcmdWithNMTDisabled + * Then run with explicitly disabling NMT, should not be any difference + * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdWithNMTDisabled { + static ProcessBuilder pb = new ProcessBuilder(); + static String pid; + + public static void main(String args[]) throws Exception { + // Grab my own PID + pid = Integer.toString(ProcessTools.getProcessId()); + + jcmdCommand("summary"); + jcmdCommand("detail"); + jcmdCommand("baseline"); + jcmdCommand("summary.diff"); + jcmdCommand("detail.diff"); + jcmdCommand("scale=GB"); + jcmdCommand("shutdown"); + } + + // Helper method for invoking different jcmd calls, all should fail with the same message saying NMT is not enabled + public static void jcmdCommand(String command) throws Exception { + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", command}); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is not enabled + output.shouldContain("Native memory tracking is not enabled"); + } +} diff --git a/hotspot/test/runtime/NMT/PrintNMTStatistics.java b/hotspot/test/runtime/NMT/PrintNMTStatistics.java new file mode 100644 index 00000000000..307ab948abd --- /dev/null +++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @key nmt regression + * @bug 8005936 + * @summary Make sure PrintNMTStatistics works on normal JVM exit + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI PrintNMTStatistics.java + */ + +import com.oracle.java.testlibrary.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.hotspot.WhiteBox; + +public class PrintNMTStatistics { + + public static void main(String args[]) throws Exception { + + // We start a new java process running with an argument and use WB API to ensure + // we have data for NMT on VM exit + if (args.length > 0) { + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + return; + } + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:NativeMemoryTracking=summary", + "+XX:+PrintNMTStatistics", + "PrintNMTStatistics", + "test"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Java Heap (reserved="); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java new file mode 100644 index 00000000000..1c25f284d4b --- /dev/null +++ b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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. + */ + + /* + * @test + * @key nmt + * @summary Trying to enable PrintNMTStatistics should result in a warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class PrintNMTStatisticsWithNMTDisabled { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+PrintNMTStatistics", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: PrintNMTStatistics is disabled, because native memory tracking is not enabled"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/ShutdownTwice.java b/hotspot/test/runtime/NMT/ShutdownTwice.java new file mode 100644 index 00000000000..1bb327aedb1 --- /dev/null +++ b/hotspot/test/runtime/NMT/ShutdownTwice.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Run shutdown twice + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice + */ + +import com.oracle.java.testlibrary.*; + +public class ShutdownTwice { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory shutdown' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is shutting down + output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + + // Run shutdown again + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT has been shutdown already + output.shouldContain("Native memory tracking has been shutdown by user"); + } +} diff --git a/hotspot/test/runtime/NMT/SummaryAfterShutdown.java b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java new file mode 100644 index 00000000000..96061f3f004 --- /dev/null +++ b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown + */ + +import com.oracle.java.testlibrary.*; + +public class SummaryAfterShutdown { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory shutdown' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is shutting down + output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT has been shutdown + output.shouldContain("Native memory tracking has been shutdown by user"); + } +} diff --git a/hotspot/test/runtime/NMT/SummarySanityCheck.java b/hotspot/test/runtime/NMT/SummarySanityCheck.java new file mode 100644 index 00000000000..cf81d5b35af --- /dev/null +++ b/hotspot/test/runtime/NMT/SummarySanityCheck.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Sanity check the output of NMT + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI SummarySanityCheck.java + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck + */ + +import com.oracle.java.testlibrary.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.hotspot.WhiteBox; + +public class SummarySanityCheck { + + private static String jcmdout; + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory summary scale=KB' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=KB"}); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + jcmdout = output.getOutput(); + // Split by '-' to get the 'groups' + String[] lines = jcmdout.split("\n"); + + if (lines.length == 0) { + throwTestException("Failed to parse jcmd output"); + } + + int totalCommitted = 0, totalReserved = 0; + int totalCommittedSum = 0, totalReservedSum = 0; + + // Match '- (reserved=KB, committed=KB) + Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB\\)"); + // Match 'Total: reserved=KB, committed=KB' + Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?\\d+)KB,\\s\\scommitted=(?\\d+)KB"); + + for (int i = 0; i < lines.length; i++) { + if (lines[i].startsWith("Total")) { + Matcher totalMemoryMatcher = totalMemoryPattern.matcher(lines[i]); + + if (totalMemoryMatcher.matches() && totalMemoryMatcher.groupCount() == 2) { + totalCommitted = Integer.parseInt(totalMemoryMatcher.group("committed")); + totalReserved = Integer.parseInt(totalMemoryMatcher.group("reserved")); + } else { + throwTestException("Failed to match the expected groups in 'Total' memory part"); + } + } else if (lines[i].startsWith("-")) { + Matcher typeMatcher = mtTypePattern.matcher(lines[i]); + if (typeMatcher.matches()) { + int typeCommitted = Integer.parseInt(typeMatcher.group("committed")); + int typeReserved = Integer.parseInt(typeMatcher.group("reserved")); + + // Make sure reserved is always less or equals + if (typeCommitted > typeReserved) { + throwTestException("Committed (" + typeCommitted + ") was more than Reserved (" + + typeReserved + ") for mtType: " + typeMatcher.group("typename")); + } + + // Add to total and compare them in the end + totalCommittedSum += typeCommitted; + totalReservedSum += typeReserved; + } else { + throwTestException("Failed to match the group on line " + i); + } + } + } + + // See if they add up correctly, rounding is a problem so make sure we're within +/- 8KB + int committedDiff = totalCommitted - totalCommittedSum; + if (committedDiff > 8 || committedDiff < -8) { + throwTestException("Total committed (" + totalCommitted + ") did not match the summarized committed (" + totalCommittedSum + ")" ); + } + + int reservedDiff = totalReserved - totalReservedSum; + if (reservedDiff > 8 || reservedDiff < -8) { + throwTestException("Total reserved (" + totalReserved + ") did not match the summarized reserved (" + totalReservedSum + ")" ); + } + } + + private static void throwTestException(String reason) throws Exception { + throw new Exception(reason + " . Stdout is :\n" + jcmdout); + } +} diff --git a/hotspot/test/testlibrary/OutputAnalyzerTest.java b/hotspot/test/testlibrary/OutputAnalyzerTest.java new file mode 100644 index 00000000000..cc48fd3ff43 --- /dev/null +++ b/hotspot/test/testlibrary/OutputAnalyzerTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @summary Test the OutputAnalyzer utility class + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class OutputAnalyzerTest { + + public static void main(String args[]) throws Exception { + + String stdout = "aaaaaa"; + String stderr = "bbbbbb"; + + OutputAnalyzer output = new OutputAnalyzer(stdout, stderr); + + if (!stdout.equals(output.getStdout())) { + throw new Exception("getStdout() returned '" + output.getStdout() + "', expected '" + stdout + "'"); + } + + if (!stderr.equals(output.getStderr())) { + throw new Exception("getStderr() returned '" + output.getStderr() + "', expected '" + stderr + "'"); + } + + try { + output.shouldContain(stdout); + output.stdoutShouldContain(stdout); + output.shouldContain(stderr); + output.stderrShouldContain(stderr); + } catch (RuntimeException e) { + throw new Exception("shouldContain() failed", e); + } + + try { + output.shouldContain("cccc"); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldContain(stderr); + throw new Exception("stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldContain(stdout); + throw new Exception("stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.shouldNotContain("cccc"); + output.stdoutShouldNotContain("cccc"); + output.stderrShouldNotContain("cccc"); + } catch (RuntimeException e) { + throw new Exception("shouldNotContain() failed", e); + } + + try { + output.shouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldNotContain(stderr); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java new file mode 100644 index 00000000000..91ad6a8c8a9 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.File; + +public final class JDKToolFinder { + + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System property + * test.jdk (set by jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { + String binPath = System.getProperty("test.jdk"); + if (binPath == null) { + throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'."); + } + + binPath += File.separatorChar + "bin" + File.separatorChar + tool; + + return binPath; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java new file mode 100644 index 00000000000..469d0c24a70 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.IOException; + +public final class OutputAnalyzer { + + private final String stdout; + private final String stderr; + private final int exitValue; + + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process + * + * @param process Process to analyze + * @throws IOException If an I/O error occurs. + */ + public OutputAnalyzer(Process process) throws IOException { + OutputBuffer output = ProcessTools.getOutput(process); + exitValue = process.exitValue(); + this.stdout = output.getStdout(); + this.stderr = output.getStderr(); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param buf String buffer to analyze + */ + public OutputAnalyzer(String buf) { + this(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout stdout buffer to analyze + * @param stderr stderr buffer to analyze + */ + public OutputAnalyzer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + exitValue = -1; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void shouldContain(String expectedString) { + if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr: [" + stdout + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void stdoutShouldContain(String expectedString) { + if (!stdout.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void stderrShouldContain(String expectedString) { + if (!stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void shouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + } + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void stdoutShouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void stderrShouldNotContain(String notExpectedString) { + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verifiy the exit value of the process + * + * @param expectedExitValue Expected exit value from process + * @throws RuntimeException If the exit value from the process did not match the expected value + */ + public void shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); + } + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return stdout + stderr; + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return stdout; + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return stderr; + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return exitValue; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java new file mode 100644 index 00000000000..b98d05650f5 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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. + */ + +package com.oracle.java.testlibrary; + +public class OutputBuffer { + private final String stdout; + private final String stderr; + + /** + * Create an OutputBuffer, a class for storing and managing stdout and stderr + * results separately + * + * @param stdout stdout result + * @param stderr stderr result + */ + public OutputBuffer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout() { + return stdout; + } + + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr() { + return stderr; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java new file mode 100644 index 00000000000..42203d17ff0 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; + +import sun.management.VMManagement; + +public final class ProcessTools { + + private ProcessTools() { + } + + /** + * Pumps stdout and stderr from running the process into a String. + * + * @param processHandler ProcessHandler to run. + * @return Output from process. + * @throws IOException If an I/O error occurs. + */ + public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException { + return getOutput(processBuilder.start()); + } + + /** + * Pumps stdout and stderr the running process into a String. + * + * @param process Process to pump. + * @return Output from process. + * @throws IOException If an I/O error occurs. + */ + public static OutputBuffer getOutput(Process process) throws IOException { + ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); + ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer); + StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer); + Thread outPumperThread = new Thread(outPumper); + Thread errPumperThread = new Thread(errPumper); + + outPumperThread.setDaemon(true); + errPumperThread.setDaemon(true); + + outPumperThread.start(); + errPumperThread.start(); + + try { + process.waitFor(); + outPumperThread.join(); + errPumperThread.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return null; + } + + return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString()); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static int getProcessId() throws Exception { + + // Get the current process id using a reflection hack + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + Field jvm = runtime.getClass().getDeclaredField("jvm"); + + jvm.setAccessible(true); + VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); + + Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); + + pid_method.setAccessible(true); + + int pid = (Integer) pid_method.invoke(mgmt); + + return pid; + } + + /** + * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) + * + * @return String[] with platform specific arguments, empty if there are none + */ + public static String[] getPlatformSpecificVMArgs() { + String osName = System.getProperty("os.name"); + String dataModel = System.getProperty("sun.arch.data.model"); + + if (osName.equals("SunOS") && dataModel.equals("64")) { + return new String[] { "-d64" }; + } + + return new String[] {}; + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested and + * with any platform specific arguments prepended + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception { + String javapath = JDKToolFinder.getJDKTool("java"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + Collections.addAll(args, command); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + + } + +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java new file mode 100644 index 00000000000..4631bce6175 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; + +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + private final OutputStream out; + private final InputStream in; + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in The stream to read from. + * @param out The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + /** + * Implements Thread.run(). Continuously read from in and write + * to out until in has reached end of stream. Abort + * on interruption. Abort on IOExceptions. + */ + @Override + public void run() { + int length; + InputStream localIn = in; + OutputStream localOut = out; + byte[] buffer = new byte[BUF_SIZE]; + + try { + while (!Thread.interrupted() && (length = localIn.read(buffer)) > 0) { + localOut.write(buffer, 0, length); + } + } catch (IOException e) { + // Just abort if something like this happens. + e.printStackTrace(); + } finally { + try { + localOut.flush(); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 4d8f24840a0..ce25c2db0cb 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -195,3 +195,6 @@ b854e70084214e9dcf1b37373f6e4b1a68760e03 jdk8-b68 499be952a291cec1dc774a84a238941d6faf772d jdk8-b71 bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72 84946404d1e1de003ed2bf218ef8d48906a90e37 jdk8-b73 +2087e24a4357eceb6432e94918e75fdc706a27d6 jdk8-b74 +ff0b73a6b3f6cea644d37d56d746a37743419fa7 jdk8-b75 +0c08593944d0cd30645f6e1e4946c51ff2b10c8c jdk8-b76 diff --git a/jaxp/makefiles/BuildJaxp.gmk b/jaxp/makefiles/BuildJaxp.gmk index e28cdf890c3..749046481a3 100644 --- a/jaxp/makefiles/BuildJaxp.gmk +++ b/jaxp/makefiles/BuildJaxp.gmk @@ -30,8 +30,6 @@ default: all include MakeBase.gmk include JavaCompilation.gmk -JAVAC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar DISABLE_JAXP_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-dep-ann,-static,-fallthrough # The generate new bytecode uses the new compiler for to generate bytecode @@ -39,7 +37,7 @@ DISABLE_JAXP_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-seria # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE_DEBUG,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-XDignore.symbol.file=true $(DISABLE_JAXP_WARNINGS) -g,\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java b/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java index ac4ae3e3e37..d7fc6bcedf0 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/Constants.java @@ -746,27 +746,29 @@ public interface Constants { /** Attributes and their corresponding names. */ - public static final byte ATTR_UNKNOWN = -1; - public static final byte ATTR_SOURCE_FILE = 0; - public static final byte ATTR_CONSTANT_VALUE = 1; - public static final byte ATTR_CODE = 2; - public static final byte ATTR_EXCEPTIONS = 3; - public static final byte ATTR_LINE_NUMBER_TABLE = 4; - public static final byte ATTR_LOCAL_VARIABLE_TABLE = 5; - public static final byte ATTR_INNER_CLASSES = 6; - public static final byte ATTR_SYNTHETIC = 7; - public static final byte ATTR_DEPRECATED = 8; - public static final byte ATTR_PMG = 9; - public static final byte ATTR_SIGNATURE = 10; - public static final byte ATTR_STACK_MAP = 11; + public static final byte ATTR_UNKNOWN = -1; + public static final byte ATTR_SOURCE_FILE = 0; + public static final byte ATTR_CONSTANT_VALUE = 1; + public static final byte ATTR_CODE = 2; + public static final byte ATTR_EXCEPTIONS = 3; + public static final byte ATTR_LINE_NUMBER_TABLE = 4; + public static final byte ATTR_LOCAL_VARIABLE_TABLE = 5; + public static final byte ATTR_INNER_CLASSES = 6; + public static final byte ATTR_SYNTHETIC = 7; + public static final byte ATTR_DEPRECATED = 8; + public static final byte ATTR_PMG = 9; + public static final byte ATTR_SIGNATURE = 10; + public static final byte ATTR_STACK_MAP = 11; + public static final byte ATTR_LOCAL_VARIABLE_TYPE_TABLE = 12; - public static final short KNOWN_ATTRIBUTES = 12; + public static final short KNOWN_ATTRIBUTES = 13; public static final String[] ATTRIBUTE_NAMES = { "SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable", "LocalVariableTable", "InnerClasses", "Synthetic", "Deprecated", - "PMGClass", "Signature", "StackMap" + "PMGClass", "Signature", "StackMap", + "LocalVariableTypeTable" }; /** Constants used in the StackMap attribute. diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java index a391d4d639a..204bb2506bb 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Attribute.java @@ -206,6 +206,9 @@ public abstract class Attribute implements Cloneable, Node, Serializable { case Constants.ATTR_LOCAL_VARIABLE_TABLE: return new LocalVariableTable(name_index, length, file, constant_pool); + case Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE: + return new LocalVariableTypeTable(name_index, length, file, constant_pool); + case Constants.ATTR_INNER_CLASSES: return new InnerClasses(name_index, length, file, constant_pool); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java index c25cce0555b..fe35197652d 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java @@ -210,6 +210,12 @@ public class DescendingVisitor implements Visitor { stack.pop(); } + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) { + stack.push(obj); + obj.accept(visitor); + stack.pop(); + } + public void visitStackMap(StackMap table) { stack.push(table); table.accept(visitor); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java index 88fe11e6a8a..32a1cc144cf 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java @@ -98,6 +98,7 @@ public class EmptyVisitor implements Visitor { public void visitLineNumberTable(LineNumberTable obj) {} public void visitLocalVariable(LocalVariable obj) {} public void visitLocalVariableTable(LocalVariableTable obj) {} + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) {} public void visitMethod(Method obj) {} public void visitSignature(Signature obj) {} public void visitSourceFile(SourceFile obj) {} diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java new file mode 100644 index 00000000000..472f53a2b6f --- /dev/null +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java @@ -0,0 +1,146 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +package com.sun.org.apache.bcel.internal.classfile; +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.sun.org.apache.bcel.internal.Constants; +import java.io.*; + +// The new table is used when generic types are about... + +//LocalVariableTable_attribute { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 local_variable_table_length; +// { u2 start_pc; +// u2 length; +// u2 name_index; +// u2 descriptor_index; +// u2 index; +// } local_variable_table[local_variable_table_length]; +// } + +//LocalVariableTypeTable_attribute { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 local_variable_type_table_length; +// { +// u2 start_pc; +// u2 length; +// u2 name_index; +// u2 signature_index; +// u2 index; +// } local_variable_type_table[local_variable_type_table_length]; +// } +// J5TODO: Needs some testing ! +public class LocalVariableTypeTable extends Attribute { + private static final long serialVersionUID = -1082157891095177114L; +private int local_variable_type_table_length; // Table of local + private LocalVariable[] local_variable_type_table; // variables + + public LocalVariableTypeTable(LocalVariableTypeTable c) { + this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), + c.getConstantPool()); + } + + public LocalVariableTypeTable(int name_index, int length, + LocalVariable[] local_variable_table, + ConstantPool constant_pool) + { + super(Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE, name_index, length, constant_pool); + setLocalVariableTable(local_variable_table); + } + + LocalVariableTypeTable(int nameIdx, int len, DataInputStream dis,ConstantPool cpool) throws IOException { + this(nameIdx, len, (LocalVariable[])null, cpool); + + local_variable_type_table_length = (dis.readUnsignedShort()); + local_variable_type_table = new LocalVariable[local_variable_type_table_length]; + + for(int i=0; i < local_variable_type_table_length; i++) + local_variable_type_table[i] = new LocalVariable(dis, cpool); + } + + @Override +public void accept(Visitor v) { + v.visitLocalVariableTypeTable(this); + } + + @Override +public final void dump(DataOutputStream file) throws IOException + { + super.dump(file); + file.writeShort(local_variable_type_table_length); + for(int i=0; i < local_variable_type_table_length; i++) + local_variable_type_table[i].dump(file); + } + + public final LocalVariable[] getLocalVariableTypeTable() { + return local_variable_type_table; + } + + public final LocalVariable getLocalVariable(int index) { + for(int i=0; i < local_variable_type_table_length; i++) + if(local_variable_type_table[i].getIndex() == index) + return local_variable_type_table[i]; + + return null; + } + + public final void setLocalVariableTable(LocalVariable[] local_variable_table) + { + this.local_variable_type_table = local_variable_table; + local_variable_type_table_length = (local_variable_table == null)? 0 : + local_variable_table.length; + } + + /** + * @return String representation. + */ + @Override +public final String toString() { + StringBuilder buf = new StringBuilder(); + + for(int i=0; i < local_variable_type_table_length; i++) { + buf.append(local_variable_type_table[i].toString()); + + if(i < local_variable_type_table_length - 1) buf.append('\n'); + } + + return buf.toString(); + } + + /** + * @return deep copy of this attribute + */ + @Override +public Attribute copy(ConstantPool constant_pool) { + LocalVariableTypeTable c = (LocalVariableTypeTable)clone(); + + c.local_variable_type_table = new LocalVariable[local_variable_type_table_length]; + for(int i=0; i < local_variable_type_table_length; i++) + c.local_variable_type_table[i] = local_variable_type_table[i].copy(); + + c.constant_pool = constant_pool; + return c; + } + + public final int getTableLength() { return local_variable_type_table_length; } +} diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java index a66c7ad2927..a076768700c 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/classfile/Visitor.java @@ -94,6 +94,7 @@ public interface Visitor { public void visitLineNumberTable(LineNumberTable obj); public void visitLocalVariable(LocalVariable obj); public void visitLocalVariableTable(LocalVariableTable obj); + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj); public void visitMethod(Method obj); public void visitSignature(Signature obj); public void visitSourceFile(SourceFile obj); diff --git a/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java b/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java index a58172a9114..34da00768cd 100644 --- a/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java +++ b/jaxp/src/com/sun/org/apache/bcel/internal/generic/MethodGen.java @@ -258,6 +258,23 @@ public class MethodGen extends FieldGenOrMethodGen { addLocalVariable(l.getName(), Type.getType(l.getSignature()), l.getIndex(), start, end); } + } else if (a instanceof LocalVariableTypeTable) { + LocalVariable[] lv = ((LocalVariableTypeTable) a).getLocalVariableTypeTable(); + removeLocalVariables(); + for (int k = 0; k < lv.length; k++) { + LocalVariable l = lv[k]; + InstructionHandle start = il.findHandle(l.getStartPC()); + InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength()); + // Repair malformed handles + if (null == start) { + start = il.getStart(); + } + if (null == end) { + end = il.getEnd(); + } + addLocalVariable(l.getName(), Type.getType(l.getSignature()), l + .getIndex(), start, end); + } } else addCodeAttribute(a); } diff --git a/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java b/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java index 39c76ed428f..abd0a7ca0af 100644 --- a/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java +++ b/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java @@ -68,7 +68,7 @@ class SchemaFactoryFinder { // Use try/catch block to support applets try { debug = ss.getSystemProperty("jaxp.debug") != null; - } catch (Exception _) { + } catch (Exception unused) { debug = false; } } @@ -113,7 +113,7 @@ class SchemaFactoryFinder { debugPrintln("using thread context class loader ("+classLoader+") for search"); return; } - } catch( Throwable _ ) { + } catch( Throwable unused ) { ; // getContextClassLoader() undefined in JDK1.1 } diff --git a/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java b/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java index 6db1dae1794..b22120da26a 100644 --- a/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java +++ b/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java @@ -56,7 +56,7 @@ class XPathFactoryFinder { // Use try/catch block to support applets try { debug = ss.getSystemProperty("jaxp.debug") != null; - } catch (Exception _) { + } catch (Exception unused) { debug = false; } } @@ -111,7 +111,7 @@ class XPathFactoryFinder { debugPrintln("using thread context class loader ("+classLoader+") for search"); return; } - } catch( Throwable _ ) { + } catch( Throwable unused ) { ; // getContextClassLoader() undefined in JDK1.1 } diff --git a/jaxws/.hgtags b/jaxws/.hgtags index f4bf9b21b81..54f020a17c1 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -195,3 +195,6 @@ d3fe408f3a9ad250bc9a4e9365bdfc3f28c1d3f4 jdk8-b68 f577a39c9fb3d5820248c13c2cc74a192a9313e0 jdk8-b71 d9707230294d54e695e745a90de6112909100f12 jdk8-b72 c606f644a5d9118c14b5822738bf23c300f14f24 jdk8-b73 +12db3c5a3393b03eeb09ff26f418c4420c21aaab jdk8-b74 +966bf9f3c41a59ff5d86ff4275291c52f329f984 jdk8-b75 +c4853f3f0e89ac60aa5b517f5f224f0f60e08577 jdk8-b76 diff --git a/jaxws/makefiles/BuildJaxws.gmk b/jaxws/makefiles/BuildJaxws.gmk index c1b092d64bc..348cba90780 100644 --- a/jaxws/makefiles/BuildJaxws.gmk +++ b/jaxws/makefiles/BuildJaxws.gmk @@ -30,8 +30,6 @@ include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk -JAVAC_JARS ?= -Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar DISABLE_JAXWS_WARNINGS:=-Xlint:all,-varargs,-rawtypes,-deprecation,-unchecked,-serial,-dep-ann,-cast,-fallthrough,-static # The generate new bytecode uses the new compiler for to generate bytecode @@ -39,7 +37,7 @@ DISABLE_JAXWS_WARNINGS:=-Xlint:all,-varargs,-rawtypes,-deprecation,-unchecked,-s # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE_DEBUG,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-XDignore.symbol.file=true $(DISABLE_JAXWS_WARNINGS) -g,\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) diff --git a/jdk/.hgtags b/jdk/.hgtags index dbc8d128f1f..ea4808559e0 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -196,3 +196,5 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 32a57e645e012a1f0665c075969ca598e0dbb948 jdk8-b72 733885f57e14cc27f5a5ff0dffe641d2fa3c704a jdk8-b73 57d5d954462831ac353a1f40d3bb05ddb4620952 jdk8-b74 +4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75 +3a263052866137b645ab86498a43693ff5c19e69 jdk8-b76 diff --git a/jdk/make/common/shared/Defs-solaris.gmk b/jdk/make/common/shared/Defs-solaris.gmk index 4bbc5b77a8c..c888a98a5da 100644 --- a/jdk/make/common/shared/Defs-solaris.gmk +++ b/jdk/make/common/shared/Defs-solaris.gmk @@ -211,7 +211,9 @@ ifeq ($(ARCH_FAMILY),sparc) MAPFILE_EXCEPTIONS = \ (libjdgaSUNWafb|libjdgaSUNWcg6|libjdgaSUNWffb|libjdgaSUNWm64|libxinerama) else - MAPFILE_EXCEPTIONS = () + # At present there are no exceptions for non + # SPARC. Use a harmless value. + MAPFILE_EXCEPTIONS = (NO_EXCEPTIONS) endif # Macro to check it's input file for banned dependencies and verify the diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index c73a3b755d6..c4a96d73c5f 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -1486,26 +1486,6 @@ endif ###################################################### sane-gcc-compiler: ifndef OPENJDK - ifeq ($(PLATFORM), solaris) - @if [ -r $(GCC_COMPILER_PATH) ]; then \ - if [ ! "$(GCC_VER)" = $(REQUIRED_GCC_VER) ]; then \ - $(ECHO) "ERROR: The Solaris GCC compiler version must be $(REQUIRED_GCC_VER). \n" \ - " You are using the following compiler version: $(GCC_VER) \n" \ - " The compiler was obtained from the following location: \n" \ - " $(GCC_COMPILER_PATH) \n" \ - " Please change your compiler. \n" \ - "" >> $(ERROR_FILE) ; \ - fi \ - else \ - $(ECHO) "ERROR: You do not have a valid GCC_COMPILER_PATH setting. \n" \ - " Please check your access to \n" \ - " $(GCC_COMPILER_PATH) \n" \ - " and/or check your value of ALT_GCC_COMPILER_PATH. \n" \ - " This will affect you if you build the plugin target. \n" \ - "" >> $(ERROR_FILE) ; \ - fi - endif - ifeq ($(PLATFORM), linux) ifeq ($(ARCH_DATA_MODEL), 32) ifdef ALT_GCC29_COMPILER_PATH diff --git a/jdk/make/netbeans/common/architectures/arch-x86_64.properties b/jdk/make/netbeans/common/architectures/arch-x86_64.properties new file mode 100644 index 00000000000..eac11240e57 --- /dev/null +++ b/jdk/make/netbeans/common/architectures/arch-x86_64.properties @@ -0,0 +1,32 @@ +# +# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +arch=x86_64 diff --git a/jdk/make/netbeans/common/architectures/name-Macosx.properties b/jdk/make/netbeans/common/architectures/name-Macosx.properties new file mode 100644 index 00000000000..05744c7f05c --- /dev/null +++ b/jdk/make/netbeans/common/architectures/name-Macosx.properties @@ -0,0 +1,32 @@ +# +# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +platform=macosx diff --git a/jdk/make/netbeans/common/java-data-native.ent b/jdk/make/netbeans/common/java-data-native.ent index a801e821db6..8db2a86d618 100644 --- a/jdk/make/netbeans/common/java-data-native.ent +++ b/jdk/make/netbeans/common/java-data-native.ent @@ -39,11 +39,11 @@ ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes ${root}/build/${platform}-${arch}/docs/api - 1.7 + 1.8 ${root}/test - 1.7 + 1.8 diff --git a/jdk/make/netbeans/common/java-data-no-native.ent b/jdk/make/netbeans/common/java-data-no-native.ent index a204f3a6f17..240ec4aadc9 100644 --- a/jdk/make/netbeans/common/java-data-no-native.ent +++ b/jdk/make/netbeans/common/java-data-no-native.ent @@ -37,11 +37,11 @@ ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes ${root}/build/${platform}-${arch}/docs/api - 1.7 + 1.8 ${root}/test - 1.7 + 1.8 diff --git a/jdk/make/netbeans/common/make.xml b/jdk/make/netbeans/common/make.xml index a61f04f07db..ee1a47a4fe1 100644 --- a/jdk/make/netbeans/common/make.xml +++ b/jdk/make/netbeans/common/make.xml @@ -33,7 +33,7 @@ - + @@ -42,6 +42,11 @@ + + + + + diff --git a/jdk/make/netbeans/common/shared.xml b/jdk/make/netbeans/common/shared.xml index 7c2b8095f79..ba104445273 100644 --- a/jdk/make/netbeans/common/shared.xml +++ b/jdk/make/netbeans/common/shared.xml @@ -85,6 +85,9 @@ + + + @@ -126,10 +129,6 @@ - - - - diff --git a/jdk/makefiles/CopyFiles.gmk b/jdk/makefiles/CopyFiles.gmk index 2885639af6f..9c4dc0d7dec 100644 --- a/jdk/makefiles/CopyFiles.gmk +++ b/jdk/makefiles/CopyFiles.gmk @@ -288,10 +288,12 @@ endif ifeq ($(OPENJDK_TARGET_OS),windows) MSVCR_TARGET := $(JDK_OUTPUTDIR)/bin/$(notdir $(MSVCR_DLL)) + # Chmod to avoid permission issues if bundles are unpacked on unix platforms. $(MSVCR_TARGET): $(MSVCR_DLL) $(MKDIR) -p $(@D) $(RM) $@ $(CP) $< $@ + $(CHMOD) a+rx $@ COPY_FILES += $(MSVCR_TARGET) endif diff --git a/jdk/makefiles/CreateJars.gmk b/jdk/makefiles/CreateJars.gmk index dc93edb7e6a..fae6d52d441 100644 --- a/jdk/makefiles/CreateJars.gmk +++ b/jdk/makefiles/CreateJars.gmk @@ -836,7 +836,7 @@ EXPORTED_PRIVATE_PKGS = com.sun.servicetag \ $(IMAGES_OUTPUTDIR)/symbols/_the.symbols: $(IMAGES_OUTPUTDIR)/lib/rt.jar $(RM) -r $(IMAGES_OUTPUTDIR)/symbols/META-INF/sym $(MKDIR) -p $(IMAGES_OUTPUTDIR)/symbols/META-INF/sym - $(JAVA) $(JAVAC_JARS) \ + $(JAVA) $(NEW_JAVAC) \ -bootclasspath $(JDK_OUTPUTDIR)/classes \ -XDprocess.packages -proc:only \ -processor com.sun.tools.javac.sym.CreateSymbols \ diff --git a/jdk/makefiles/GensrcSwing.gmk b/jdk/makefiles/GensrcSwing.gmk index 7a554f26da6..9f3bff1ba41 100644 --- a/jdk/makefiles/GensrcSwing.gmk +++ b/jdk/makefiles/GensrcSwing.gmk @@ -71,7 +71,7 @@ SWINGBEAN_DEBUG_FLAG = false $(JDK_OUTPUTDIR)/gensrc_no_srczip/_the.generated_beaninfo: $(BEANS_SRC) $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing/SwingBeanInfoBase.java $(JDK_OUTPUTDIR)/gensrc/sun/swing/BeanInfoUtils.java $(BUILD_TOOLS) $(ECHO) Generating beaninfo $(MKDIR) -p $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing - $(JAVA) -Djava.awt.headless=true -jar $(JAVADOC_JARS) -doclet GenDocletBeanInfo \ + $(JAVA) -Djava.awt.headless=true $(NEW_JAVADOC) -doclet GenDocletBeanInfo \ -x $(SWINGBEAN_DEBUG_FLAG) -d $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing \ -t $(DOCLETSRC_DIR)/SwingBeanInfo.template -docletpath $(JDK_OUTPUTDIR)/btclasses \ -XDignore.symbol.file=true \ diff --git a/jdk/makefiles/Setup.gmk b/jdk/makefiles/Setup.gmk index 5ca687f5a1d..95e7b20f39c 100644 --- a/jdk/makefiles/Setup.gmk +++ b/jdk/makefiles/Setup.gmk @@ -23,10 +23,6 @@ # questions. # -JAVAC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar -JAVAH_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar" -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar -JAVADOC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar" -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar - DISABLE_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-dep-ann,-static,-fallthrough,-try,-varargs,-empty,-finally # The generate old bytecode javac setup uses the new compiler to compile for the @@ -34,7 +30,7 @@ DISABLE_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-de # Thus we force the target bytecode to 7. $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-source 7 -target 7 -bootclasspath $(BOOT_RTJAR) $(DISABLE_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -43,8 +39,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ # new jdk. This new bytecode might only be possible to run using the new jvm. $(eval $(call SetupJavaCompiler,GENERATE_JDKBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ - JAVAH:=$(JAVAH_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-bootclasspath $(JDK_OUTPUTDIR)/classes -source 8 -target 8 -encoding ascii -XDignore.symbol.file=true $(DISABLE_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -55,7 +50,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_JDKBYTECODE,\ # (it will be in "make images") therefore we use classes instead. $(eval $(call SetupJavaCompiler,GENERATE_USINGJDKBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-bootclasspath $(JDK_OUTPUTDIR)/classes $(DISABLE_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java index 9e891fc7c87..f6ff030263e 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java @@ -1287,19 +1287,24 @@ class Attribute implements Comparable { if (localRef == 0) { globalRef = null; // N.B. global null reference is -1 } else { - globalRef = holder.getCPMap()[localRef]; - if (e.refKind == CONSTANT_Signature + Entry[] cpMap = holder.getCPMap(); + globalRef = (localRef >= 0 && localRef < cpMap.length + ? cpMap[localRef] + : null); + byte tag = e.refKind; + if (globalRef != null && tag == CONSTANT_Signature && globalRef.getTag() == CONSTANT_Utf8) { // Cf. ClassReader.readSignatureRef. String typeName = globalRef.stringValue(); globalRef = ConstantPool.getSignatureEntry(typeName); - } else if (e.refKind == CONSTANT_FieldSpecific) { - assert(globalRef.getTag() >= CONSTANT_Integer); - assert(globalRef.getTag() <= CONSTANT_String || - globalRef.getTag() >= CONSTANT_MethodHandle); - assert(globalRef.getTag() <= CONSTANT_MethodType); - } else if (e.refKind < CONSTANT_GroupFirst) { - assert(e.refKind == globalRef.getTag()); + } + String got = (globalRef == null + ? "invalid CP index" + : "type=" + ConstantPool.tagName(globalRef.tag)); + if (globalRef == null || !globalRef.tagMatches(tag)) { + throw new IllegalArgumentException( + "Bad constant, expected type=" + + ConstantPool.tagName(tag) + " got " + got); } } out.putRef(bandIndex, globalRef); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java index 2ca2d0926c6..3df8706da37 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -54,6 +54,7 @@ class ClassReader { Package pkg; Class cls; long inPos; + long constantPoolLimit = -1; DataInputStream in; Map attrDefs; Map attrCommands; @@ -117,15 +118,33 @@ class ClassReader { private Entry readRef(byte tag) throws IOException { Entry e = readRef(); - assert(e != null); assert(!(e instanceof UnresolvedEntry)); - assert(e.tagMatches(tag)); + checkTag(e, tag); return e; } + /** Throw a ClassFormatException if the entry does not match the expected tag type. */ + private Entry checkTag(Entry e, byte tag) throws ClassFormatException { + if (e == null || !e.tagMatches(tag)) { + String where = (inPos == constantPoolLimit + ? " in constant pool" + : " at pos: " + inPos); + String got = (e == null + ? "null CP index" + : "type=" + ConstantPool.tagName(e.tag)); + throw new ClassFormatException("Bad constant, expected type=" + + ConstantPool.tagName(tag) + + " got "+ got + ", in File: " + cls.file.nameString + where); + } + return e; + } + private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException { + return nullOK && e == null ? null : checkTag(e, tag); + } + private Entry readRefOrNull(byte tag) throws IOException { Entry e = readRef(); - assert(e == null || e.tagMatches(tag)); + checkTag(e, tag, true); return e; } @@ -143,8 +162,10 @@ class ClassReader { private SignatureEntry readSignatureRef() throws IOException { // The class file stores a Utf8, but we want a Signature. - Entry e = readRef(CONSTANT_Utf8); - return ConstantPool.getSignatureEntry(e.stringValue()); + Entry e = readRef(CONSTANT_Signature); + return (e != null && e.getTag() == CONSTANT_Utf8) + ? ConstantPool.getSignatureEntry(e.stringValue()) + : (SignatureEntry) e; } void read() throws IOException { @@ -279,6 +300,7 @@ class ClassReader { " at pos: " + inPos); } } + constantPoolLimit = inPos; // Fix up refs, which might be out of order. while (fptr > 0) { @@ -311,25 +333,25 @@ class ClassReader { case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: - ClassEntry mclass = (ClassEntry) cpMap[ref]; - DescriptorEntry mdescr = (DescriptorEntry) cpMap[ref2]; + ClassEntry mclass = (ClassEntry) checkTag(cpMap[ref], CONSTANT_Class); + DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType); cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr); break; case CONSTANT_NameandType: - Utf8Entry mname = (Utf8Entry) cpMap[ref]; - Utf8Entry mtype = (Utf8Entry) cpMap[ref2]; + Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref], CONSTANT_Utf8); + Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature); cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype); break; case CONSTANT_MethodType: - cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]); + cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature)); break; case CONSTANT_MethodHandle: byte refKind = (byte)(-1 ^ ref); - MemberEntry memRef = (MemberEntry) cpMap[ref2]; + MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember); cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef); break; case CONSTANT_InvokeDynamic: - DescriptorEntry idescr = (DescriptorEntry) cpMap[ref2]; + DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType); cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr); // Note that ref must be resolved later, using the BootstrapMethods attribute. break; @@ -541,7 +563,8 @@ class ClassReader { code.max_locals = readUnsignedShort(); code.bytes = new byte[readInt()]; in.readFully(code.bytes); - Instruction.opcodeChecker(code.bytes); + Entry[] cpMap = cls.getCPMap(); + Instruction.opcodeChecker(code.bytes, cpMap); int nh = readUnsignedShort(); code.setHandlerCount(nh); for (int i = 0; i < nh; i++) { @@ -559,7 +582,7 @@ class ClassReader { MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle); Entry[] argRefs = new Entry[readUnsignedShort()]; for (int j = 0; j < argRefs.length; j++) { - argRefs[j] = readRef(); + argRefs[j] = readRef(CONSTANT_LoadableValue); } bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs); } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java index be4da54d247..ad2175f9993 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -243,8 +243,32 @@ class ConstantPool { return tag == CONSTANT_Double || tag == CONSTANT_Long; } - public final boolean tagMatches(int tag) { - return (this.tag == tag); + public final boolean tagMatches(int matchTag) { + if (tag == matchTag) + return true; + byte[] allowedTags; + switch (matchTag) { + case CONSTANT_All: + return true; + case CONSTANT_Signature: + return tag == CONSTANT_Utf8; // format check also? + case CONSTANT_LoadableValue: + allowedTags = LOADABLE_VALUE_TAGS; + break; + case CONSTANT_AnyMember: + allowedTags = ANY_MEMBER_TAGS; + break; + case CONSTANT_FieldSpecific: + allowedTags = FIELD_SPECIFIC_TAGS; + break; + default: + return false; + } + for (byte b : allowedTags) { + if (b == tag) + return true; + } + return false; } public String toString() { diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java index f488bede323..31ee22b059d 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -647,7 +647,7 @@ class Instruction { } } - public static void opcodeChecker(byte[] code) throws FormatException { + public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap) throws FormatException { Instruction i = at(code, 0); while (i != null) { int opcode = i.getBC(); @@ -655,6 +655,16 @@ class Instruction { String message = "illegal opcode: " + opcode + " " + i; throw new FormatException(message); } + ConstantPool.Entry e = i.getCPRef(cpMap); + if (e != null) { + byte tag = i.getCPTag(); + if (!e.tagMatches(tag)) { + String message = "illegal reference, expected type=" + + ConstantPool.tagName(tag) + ": " + + i.toString(cpMap); + throw new FormatException(message); + } + } i = i.next(); } } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java index e6990451135..47959294fd2 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java @@ -1618,6 +1618,16 @@ class PackageWriter extends BandStructure { bc_which = null; assert(false); } + if (ref != null && bc_which.index != null && !bc_which.index.contains(ref)) { + // Crash and burn with a complaint if there are funny + // references for this bytecode instruction. + // Example: invokestatic of a CONSTANT_InterfaceMethodref. + String complaint = code.getMethod() + + " contains a bytecode " + i + + " with an unsupported constant reference; please use the pass-file option on this class."; + Utils.log.warning(complaint); + throw new IOException(complaint); + } bc_codes.putByte(vbc); bc_which.putRef(ref); // handle trailing junk diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java index c7ef4ee2013..0dc88a108c7 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,6 +180,15 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { } unknownAttrCommand = uaMode.intern(); } + final String classFormatCommand; + { + String fmtMode = props.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS); + if (!(Pack200.Packer.PASS.equals(fmtMode) || + Pack200.Packer.ERROR.equals(fmtMode))) { + throw new RuntimeException("Bad option: " + Utils.CLASS_FORMAT_ERROR + " = " + fmtMode); + } + classFormatCommand = fmtMode.intern(); + } final Map attrDefs; final Map attrCommands; @@ -505,8 +514,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { } } else if (ioe instanceof ClassReader.ClassFormatException) { ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe; - // %% TODO: Do we invent a new property for this or reuse %% - if (unknownAttrCommand.equals(Pack200.Packer.PASS)) { + if (classFormatCommand.equals(Pack200.Packer.PASS)) { Utils.log.info(ce.toString()); Utils.log.warning(message + " unknown class format: " + fname); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java index 6199c77b51d..24485040378 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,6 +112,11 @@ final class PropMap implements SortedMap { // Pass through files with unrecognized attributes by default. props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); + // Pass through files with unrecognized format by default, also + // allow system property to be set + props.put(Utils.CLASS_FORMAT_ERROR, + System.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS)); + // Default effort is 5, midway between 1 and 9. props.put(Pack200.Packer.EFFORT, "5"); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java index 5edd73e21cb..ebe0960dba0 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,6 +122,12 @@ class Utils { */ static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200"; + /* + * behaviour when we hit a class format error, but not necessarily + * an unknown attribute, by default it is allowed to PASS. + */ + static final String CLASS_FORMAT_ERROR = COM_PREFIX+"class.format.error"; + // Keep a TLS point to the global data and environment. // This makes it simpler to supply environmental options // to the engine code, especially the native code. diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java index 2e259a818c8..5680cc66631 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java @@ -50,8 +50,6 @@ import javax.management.MBeanInfo; import javax.management.NotCompliantMBeanException; import com.sun.jmx.remote.util.EnvHelp; -import java.beans.BeanInfo; -import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import javax.management.AttributeNotFoundException; diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 094f0cf26d6..dab6c98e47a 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -29,12 +29,14 @@ import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Member; import java.lang.reflect.Field; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.AnnotatedType; import java.lang.ref.SoftReference; import java.io.InputStream; import java.io.ObjectStreamField; @@ -2325,6 +2327,11 @@ public final // Annotations handling private native byte[] getRawAnnotations(); + // Since 1.8 + native byte[] getRawTypeAnnotations(); + static byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return getReflectionFactory().getExecutableTypeAnnotationBytes(ex); + } native ConstantPool getConstantPool(); @@ -3068,21 +3075,12 @@ public final * @throws NullPointerException {@inheritDoc} * @since 1.5 */ + @SuppressWarnings("unchecked") public A getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); - return AnnotationSupport.getOneAnnotation(annotations, annotationClass); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent(Class annotationClass) { - Objects.requireNonNull(annotationClass); - - return getAnnotation(annotationClass) != null; + return (A) annotations.get(annotationClass); } /** @@ -3101,18 +3099,19 @@ public final */ public Annotation[] getAnnotations() { initAnnotationsIfNecessary(); - return AnnotationSupport.unpackToArray(annotations); + return AnnotationParser.toArray(annotations); } /** * @throws NullPointerException {@inheritDoc} * @since 1.8 */ + @SuppressWarnings("unchecked") public A getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); - return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass); + return (A) declaredAnnotations.get(annotationClass); } /** @@ -3131,17 +3130,7 @@ public final */ public Annotation[] getDeclaredAnnotations() { initAnnotationsIfNecessary(); - return AnnotationSupport.unpackToArray(declaredAnnotations); - } - - /** Returns one "directly" present annotation or null */ - A getDirectDeclaredAnnotation(Class annotationClass) { - Objects.requireNonNull(annotationClass); - - initAnnotationsIfNecessary(); - @SuppressWarnings("unchecked") // TODO check safe - A ret = (A)declaredAnnotations.get(annotationClass); - return ret; + return AnnotationParser.toArray(declaredAnnotations); } // Annotations cache @@ -3196,4 +3185,53 @@ public final * Maintained by the ClassValue class. */ transient ClassValue.ClassValueMap classValueMap; + + /** + * Returns an AnnotatedType object that represents the use of a type to specify + * the superclass of the entity represented by this Class. (The use of type + * Foo to specify the superclass in '... extends Foo' is distinct from the + * declaration of type Foo.) + * + * If this Class represents a class type whose declaration does not explicitly + * indicate an annotated superclass, the return value is null. + * + * If this Class represents either the Object class, an interface type, an + * array type, a primitive type, or void, the return value is null. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedSuperclass() { + return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this); +} + + /** + * Returns an array of AnnotatedType objects that represent the use of types to + * specify superinterfaces of the entity represented by this Class. (The use + * of type Foo to specify a superinterface in '... implements Foo' is + * distinct from the declaration of type Foo.) + * + * If this Class represents a class, the return value is an array + * containing objects representing the uses of interface types to specify + * interfaces implemented by the class. The order of the objects in the + * array corresponds to the order of the interface types used in the + * 'implements' clause of the declaration of this Class. + * + * If this Class represents an interface, the return value is an array + * containing objects representing the uses of interface types to specify + * interfaces directly extended by the interface. The order of the objects in + * the array corresponds to the order of the interface types used in the + * 'extends' clause of the declaration of this Class. + * + * If this Class represents a class or interface whose declaration does not + * explicitly indicate any annotated superinterfaces, the return value is an + * array of length 0. + * + * If this Class represents either the Object class, an array type, a + * primitive type, or void, the return value is an array of length 0. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedInterfaces() { + return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this); + } } diff --git a/jdk/src/share/classes/java/lang/Double.java b/jdk/src/share/classes/java/lang/Double.java index f79980f4bb8..9bdb0ca4679 100644 --- a/jdk/src/share/classes/java/lang/Double.java +++ b/jdk/src/share/classes/java/lang/Double.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -289,7 +289,7 @@ public final class Double extends Number implements Comparable { return Double.toString(d); else { // Initialized to maximum size of output. - StringBuffer answer = new StringBuffer(24); + StringBuilder answer = new StringBuilder(24); if (Math.copySign(1.0, d) == -1.0) // value is negative, answer.append("-"); // so append sign info @@ -300,8 +300,7 @@ public final class Double extends Number implements Comparable { if(d == 0.0) { answer.append("0.0p0"); - } - else { + } else { boolean subnormal = (d < DoubleConsts.MIN_NORMAL); // Isolate significand bits and OR in a high-order bit @@ -324,13 +323,14 @@ public final class Double extends Number implements Comparable { "0": signif.replaceFirst("0{1,12}$", "")); + answer.append('p'); // If the value is subnormal, use the E_min exponent // value for double; otherwise, extract and report d's // exponent (the representation of a subnormal uses // E_min -1). - answer.append("p" + (subnormal ? - DoubleConsts.MIN_EXPONENT: - Math.getExponent(d) )); + answer.append(subnormal ? + DoubleConsts.MIN_EXPONENT: + Math.getExponent(d)); } return answer.toString(); } diff --git a/jdk/src/share/classes/java/lang/Package.java b/jdk/src/share/classes/java/lang/Package.java index 744a292d6ee..234f807181a 100644 --- a/jdk/src/share/classes/java/lang/Package.java +++ b/jdk/src/share/classes/java/lang/Package.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -385,15 +385,6 @@ public class Package implements java.lang.reflect.AnnotatedElement { return getPackageInfo().getAnnotation(annotationClass); } - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent( - Class annotationClass) { - return getPackageInfo().isAnnotationPresent(annotationClass); - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java index a6206e60391..45ea7190ae8 100644 --- a/jdk/src/share/classes/java/lang/System.java +++ b/jdk/src/share/classes/java/lang/System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -25,7 +25,7 @@ package java.lang; import java.io.*; -import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; import java.util.Properties; import java.util.PropertyPermission; import java.util.StringTokenizer; @@ -1196,8 +1196,11 @@ public final class System { public AnnotationType getAnnotationType(Class klass) { return klass.getAnnotationType(); } - public A getDirectDeclaredAnnotation(Class klass, Class anno) { - return klass.getDirectDeclaredAnnotation(anno); + public byte[] getRawClassTypeAnnotations(Class klass) { + return klass.getRawTypeAnnotations(); + } + public byte[] getRawExecutableTypeAnnotations(Executable executable) { + return Class.getExecutableTypeAnnotationBytes(executable); } public > E[] getEnumConstantsShared(Class klass) { diff --git a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java b/jdk/src/share/classes/java/lang/annotation/ContainedBy.java deleted file mode 100644 index 4f032863791..00000000000 --- a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.annotation; - -/** - * The annotation type {@code java.lang.annotation.ContainedBy} is - * used to indicate that the annotation type whose declaration it - * (meta-)annotates is repeatable. The value of - * {@code @ContainedBy} indicates the containing annotation - * type for the repeatable annotation type. - * - *

The pair of annotation types {@code @ContainedBy} and - * {@link java.lang.annotation.ContainerFor @ContainerFor} are used to - * indicate that annotation types are repeatable. Specifically: - * - *

- * - *

- * An inconsistent pair of {@code @ContainedBy} and - * {@code @ContainerFor} annotations on a repeatable annotation type - * and its containing annotation type (JLS 9.6) will lead to - * compile-time errors and runtime exceptions when using reflection to - * read annotations of a repeatable type. - * - * @see java.lang.annotation.ContainerFor - * @since 1.8 - * @jls 9.6 Annotation Types - * @jls 9.7 Annotations - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE) -public @interface ContainedBy { - /** - * Indicates the containing annotation type for the - * repeatable annotation type. - */ - Class value(); -} diff --git a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java b/jdk/src/share/classes/java/lang/annotation/ContainerFor.java deleted file mode 100644 index 62f3446e021..00000000000 --- a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.annotation; - -/** - * The annotation type {@code java.lang.annotation.ContainerFor} is - * used to indicate that the annotation type whose declaration it - * (meta-)annotates is a containing annotation type. The - * value of {@code @ContainerFor} indicates the repeatable - * annotation type for the containing annotation type. - * - *

The pair of annotation types {@link - * java.lang.annotation.ContainedBy @ContainedBy} and - * {@code @ContainerFor} are used to indicate that annotation types - * are repeatable. Specifically: - * - *

    - *
  • The annotation type {@code @ContainedBy} is used on the - * declaration of a repeatable annotation type (JLS 9.6) to indicate - * its containing annotation type. - * - *
  • The annotation type {@code @ContainerFor} is used on the - * declaration of a containing annotation type (JLS 9.6) to indicate - * the repeatable annotation type for which it serves as the - * containing annotation type. - *
- * - *

- * An inconsistent pair of {@code @ContainedBy} and - * {@code @ContainerFor} annotations on a repeatable annotation type - * and its containing annotation type (JLS 9.6) will lead to - * compile-time errors and runtime exceptions when using reflection to - * read annotations of a repeatable type. - * - * @see java.lang.annotation.ContainedBy - * @since 1.8 - * @jls 9.6 Annotation Types - * @jls 9.7 Annotations - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE) -public @interface ContainerFor { - - /** - * Indicates the repeatable annotation type for the containing - * annotation type. - */ - Class value(); -} diff --git a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java index b24e3034179..37d00a98b40 100644 --- a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java +++ b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,10 +27,9 @@ package java.lang.annotation; import java.util.Objects; /** - * Thrown to indicate that an annotation type whose declaration is - * (meta-)annotated with a {@link ContainerFor} annotation is not, in - * fact, the containing annotation type of the type named by {@link - * ContainerFor}. + * Thrown to indicate that an annotation type expected to act as a + * container for another annotation type by virture of an @Repeatable + * annotation, does not act as a container. * * @see java.lang.reflect.AnnotatedElement * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java index baaec298a85..9986aef6cf7 100644 --- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java @@ -180,14 +180,6 @@ public class AccessibleObject implements AnnotatedElement { throw new AssertionError("All subclasses should override this method"); } - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent(Class annotationClass) { - return getAnnotation(annotationClass) != null; - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java new file mode 100644 index 00000000000..e84a3360fdd --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, 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 java.lang.reflect; + + +/** + * AnnotatedArrayType represents the use of an array type, whose component + * type may itself represent the annotated use of a type. + * + * @since 1.8 + */ +public interface AnnotatedArrayType extends AnnotatedType { + + /** + * Returns the annotated generic component type of this array type. + * + * @return the annotated generic component type of this array type + */ + AnnotatedType getAnnotatedGenericComponentType(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java index 58a07350f36..85472ff5b00 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,24 @@ import java.lang.annotation.Annotation; * arrays returned by accessors for array-valued enum members; it will * have no affect on the arrays returned to other callers. * + *

An annotation A is directly present on an element E if the + * RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute + * associated with E either: + *

    + *
  • contains A; or + *
  • for invocations of get[Declared]Annotations(Class), + * contains A or exactly one annotation C whose type is the containing + * annotation type of A's type (JLS 9.6) and whose value element contains A + *
+ * + *

An annotation A is present on an element E if either: + *

    + *
  • A is directly present on E; or + *
  • There are no annotations of A's type which are directly present + * on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is + * present on the superclass of E + *
+ * *

If an annotation returned by a method in this interface contains * (directly or indirectly) a {@link Class}-valued member referring to * a class that is not accessible in this VM, attempting to read the class @@ -50,7 +68,7 @@ import java.lang.annotation.Annotation; * containing annotation type of T will result in an * InvalidContainerAnnotationError. * - *

Finally, Attempting to read a member whose definition has evolved + *

Finally, attempting to read a member whose definition has evolved * incompatibly will result in a {@link * java.lang.annotation.AnnotationTypeMismatchException} or an * {@link java.lang.annotation.IncompleteAnnotationException}. @@ -70,6 +88,12 @@ public interface AnnotatedElement { * is present on this element, else false. This method * is designed primarily for convenient access to marker annotations. * + *

The truth value returned by this method is equivalent to: + * {@code getAnnotation(annotationClass) != null} + * + *

The body of the default method is specified to be the code + * above. + * * @param annotationClass the Class object corresponding to the * annotation type * @return true if an annotation for the specified annotation @@ -77,7 +101,9 @@ public interface AnnotatedElement { * @throws NullPointerException if the given annotation class is null * @since 1.5 */ - boolean isAnnotationPresent(Class annotationClass); + default boolean isAnnotationPresent(Class annotationClass) { + return getAnnotation(annotationClass) != null; + } /** * Returns this element's annotation for the specified type if @@ -110,12 +136,15 @@ public interface AnnotatedElement { T[] getAnnotations(Class annotationClass); /** - * Returns all annotations present on this element. (Returns an array - * of length zero if this element has no annotations.) The caller of - * this method is free to modify the returned array; it will have no - * effect on the arrays returned to other callers. + * Returns annotations that are present on this element. * - * @return all annotations present on this element + * If there are no annotations present on this element, the return + * value is an array of length 0. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. + * + * @return annotations present on this element * @since 1.5 */ Annotation[] getAnnotations(); @@ -157,14 +186,16 @@ public interface AnnotatedElement { T[] getDeclaredAnnotations(Class annotationClass); /** - * Returns all annotations that are directly present on this - * element. This method ignores inherited annotations. (Returns - * an array of length zero if no annotations are directly present - * on this element.) The caller of this method is free to modify - * the returned array; it will have no effect on the arrays - * returned to other callers. + * Returns annotations that are directly present on this element. + * This method ignores inherited annotations. * - * @return All annotations directly present on this element + * If there are no annotations directly present on this element, + * the return value is an array of length 0. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. + * + * @return annotations directly present on this element * @since 1.5 */ Annotation[] getDeclaredAnnotations(); diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java new file mode 100644 index 00000000000..4fa089e318c --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 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 java.lang.reflect; + +/** + * AnnotatedParameterizedType represents the use of a parameterized type, + * whose type arguments may themselves represent annotated uses of types. + * + * @since 1.8 + */ +public interface AnnotatedParameterizedType extends AnnotatedType { + + /** + * Returns the annotated actual type arguments of this parameterized type. + * + * @return the annotated actual type arguments of this parameterized type + */ + AnnotatedType[] getAnnotatedActualTypeArguments(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java new file mode 100644 index 00000000000..d1ee79f14f4 --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 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 java.lang.reflect; + +/** + * AnnotatedType represents the annotated use of a type in the program + * currently running in this VM. The use may be of any type in the Java + * programming language, including an array type, a parameterized type, a type + * variable, or a wildcard type. + * + * @since 1.8 + */ +public interface AnnotatedType extends AnnotatedElement { + + /** + * Returns the underlying type that this annotated type represents. + * + * @return the type this annotated type represents + */ + public Type getType(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java new file mode 100644 index 00000000000..3580a14442f --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, 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 java.lang.reflect; + +/** + * AnnotatedTypeVariable represents the use of a type variable, whose + * declaration may have bounds which themselves represent annotated uses of + * types. + * + * @since 1.8 + */ +public interface AnnotatedTypeVariable extends AnnotatedType { + + /** + * Returns the annotated bounds of this type variable. + * + * @return the annotated bounds of this type variable + */ + AnnotatedType[] getAnnotatedBounds(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java new file mode 100644 index 00000000000..c357eb9d0bc --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012, 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 java.lang.reflect; + +/** + * AnnotatedWildcardType represents the use of a wildcard type argument, whose + * upper or lower bounds may themselves represent annotated uses of types. + * + * @since 1.8 + */ +public interface AnnotatedWildcardType extends AnnotatedType { + + /** + * Returns the annotated lower bounds of this wildcard type. + * + * @return the annotated lower bounds of this wildcard type + */ + AnnotatedType[] getAnnotatedLowerBounds(); + + /** + * Returns the annotated upper bounds of this wildcard type. + * + * @return the annotated upper bounds of this wildcard type + */ + AnnotatedType[] getAnnotatedUpperBounds(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/Constructor.java b/jdk/src/share/classes/java/lang/reflect/Constructor.java index 1973e820950..bbfd1d5ab9d 100644 --- a/jdk/src/share/classes/java/lang/reflect/Constructor.java +++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java @@ -154,6 +154,10 @@ public final class Constructor extends Executable { byte[] getAnnotationBytes() { return annotations; } + @Override + byte[] getTypeAnnotationBytes() { + return typeAnnotations; + } /** * {@inheritDoc} @@ -523,4 +527,12 @@ public final class Constructor extends Executable { } } } + + /** + * {@inheritDoc} + * @since 1.8 + */ + public AnnotatedType getAnnotatedReturnType() { + return getAnnotatedReturnType0(getDeclaringClass()); + } } diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index f2befd2dcdd..ad1a5808632 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -26,11 +26,12 @@ package java.lang.reflect; import java.lang.annotation.*; -import java.util.Collections; import java.util.Map; import java.util.Objects; import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.annotation.TypeAnnotation; import sun.reflect.generics.repository.ConstructorRepository; /** @@ -50,6 +51,7 @@ public abstract class Executable extends AccessibleObject * Accessor method to allow code sharing */ abstract byte[] getAnnotationBytes(); + abstract byte[] getTypeAnnotationBytes(); /** * Does the Executable have generic information. @@ -435,8 +437,7 @@ public abstract class Executable extends AccessibleObject */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** @@ -454,7 +455,7 @@ public abstract class Executable extends AccessibleObject * {@inheritDoc} */ public Annotation[] getDeclaredAnnotations() { - return AnnotationSupport.unpackToArray(declaredAnnotations()); + return AnnotationParser.toArray(declaredAnnotations()); } private transient Map, Annotation> declaredAnnotations; @@ -470,4 +471,86 @@ public abstract class Executable extends AccessibleObject return declaredAnnotations; } + + /* Helper for subclasses of Executable. + * + * Returns an AnnotatedType object that represents the use of a type to + * specify the return type of the method/constructor represented by this + * Executable. + * + * @since 1.8 + */ + AnnotatedType getAnnotatedReturnType0(Type returnType) { + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + returnType, + TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE); + } + + /** + * Returns an AnnotatedType object that represents the use of a type to + * specify the receiver type of the method/constructor represented by this + * Executable. The receiver type of a method/constructor is available only + * if the method/constructor declares a formal parameter called 'this'. + * + * Returns null if this Executable represents a constructor or instance + * method that either declares no formal parameter called 'this', or + * declares a formal parameter called 'this' with no annotations on its + * type. + * + * Returns null if this Executable represents a static method. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedReceiverType() { + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getDeclaringClass(), + TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE); + } + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to specify formal parameter types of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the formal parameter types in the + * declaration of the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * parameters. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedParameterTypes() { + throw new UnsupportedOperationException("Not yet"); + } + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to specify the declared exceptions of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the exception types in the declaration of + * the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * exceptions. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedExceptionTypes() { + return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericExceptionTypes(), + TypeAnnotation.TypeAnnotationTarget.THROWS); + } + } diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index e5471459586..df38832eb15 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,8 @@ import java.util.Map; import java.util.Objects; import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationSupport; - +import sun.reflect.annotation.TypeAnnotation; +import sun.reflect.annotation.TypeAnnotationParser; /** * A {@code Field} provides information about, and dynamic access to, a @@ -1020,8 +1021,7 @@ class Field extends AccessibleObject implements Member { */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** @@ -1039,7 +1039,7 @@ class Field extends AccessibleObject implements Member { * {@inheritDoc} */ public Annotation[] getDeclaredAnnotations() { - return AnnotationSupport.unpackToArray(declaredAnnotations()); + return AnnotationParser.toArray(declaredAnnotations()); } private transient Map, Annotation> declaredAnnotations; @@ -1053,4 +1053,20 @@ class Field extends AccessibleObject implements Member { } return declaredAnnotations; } + + /** + * Returns an AnnotatedType object that represents the use of a type to specify + * the declared type of the field represented by this Field. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedType() { + return TypeAnnotationParser.buildAnnotatedType(typeAnnotations, + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericType(), + TypeAnnotation.TypeAnnotationTarget.FIELD_TYPE); +} } diff --git a/jdk/src/share/classes/java/lang/reflect/Method.java b/jdk/src/share/classes/java/lang/reflect/Method.java index a7beb011400..1507c77194a 100644 --- a/jdk/src/share/classes/java/lang/reflect/Method.java +++ b/jdk/src/share/classes/java/lang/reflect/Method.java @@ -165,6 +165,10 @@ public final class Method extends Executable { byte[] getAnnotationBytes() { return annotations; } + @Override + byte[] getTypeAnnotationBytes() { + return typeAnnotations; + } /** * {@inheritDoc} @@ -621,6 +625,14 @@ public final class Method extends Executable { return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); } + /** + * {@inheritDoc} + * @since 1.8 + */ + public AnnotatedType getAnnotatedReturnType() { + return getAnnotatedReturnType0(getGenericReturnType()); + } + @Override void handleParameterNumberMismatch(int resultLength, int numParameters) { throw new AnnotationFormatError("Parameter annotations don't match number of parameters"); diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 6eed6926be0..04bc274ca9f 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -233,8 +233,7 @@ public final class Parameter implements AnnotatedElement { */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** @@ -281,14 +280,6 @@ public final class Parameter implements AnnotatedElement { return getDeclaredAnnotations(); } - /** - * @throws NullPointerException {@inheritDoc} - */ - public boolean isAnnotationPresent( - Class annotationClass) { - return getAnnotation(annotationClass) != null; - } - private transient Map, Annotation> declaredAnnotations; private synchronized Map, Annotation> declaredAnnotations() { diff --git a/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java b/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java index 80311d240e6..c3ac1557b85 100644 --- a/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java +++ b/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -128,6 +128,10 @@ class ReflectAccess implements sun.reflect.LangReflectAccess { return c.getRawParameterAnnotations(); } + public byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return ex.getTypeAnnotationBytes(); + } + // // Copying routines, needed to quickly fabricate new Field, // Method, and Constructor objects from templates diff --git a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java index b0ff7880cda..42027e0041c 100644 --- a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java +++ b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,4 +86,16 @@ public interface TypeVariable extends Type, Annota * @return the name of this type variable, as it appears in the source code */ String getName(); + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to denote the upper bounds of the type parameter represented by + * this TypeVariable. The order of the objects in the array corresponds to + * the order of the bounds in the declaration of the type parameter. + * + * Returns an array of length 0 if the type parameter declares no bounds. + * + * @since 1.8 + */ + AnnotatedType[] getAnnotatedBounds(); } diff --git a/jdk/src/share/classes/java/math/BigDecimal.java b/jdk/src/share/classes/java/math/BigDecimal.java index d95b1cb27b3..b7f6380948e 100644 --- a/jdk/src/share/classes/java/math/BigDecimal.java +++ b/jdk/src/share/classes/java/math/BigDecimal.java @@ -3537,13 +3537,25 @@ public class BigDecimal extends Number implements Comparable { else return expandBigIntegerTenPowers(n); } - // BigInteger.pow is slow, so make 10**n by constructing a - // BigInteger from a character string (still not very fast) - char tenpow[] = new char[n + 1]; - tenpow[0] = '1'; - for (int i = 1; i <= n; i++) - tenpow[i] = '0'; - return new BigInteger(tenpow,1, tenpow.length); + + if (n < 1024*524288) { + // BigInteger.pow is slow, so make 10**n by constructing a + // BigInteger from a character string (still not very fast) + // which occupies no more than 1GB (!) of memory. + char tenpow[] = new char[n + 1]; + tenpow[0] = '1'; + for (int i = 1; i <= n; i++) { + tenpow[i] = '0'; + } + return new BigInteger(tenpow, 1, tenpow.length); + } + + if ((n & 0x1) == 0x1) { + return BigInteger.TEN.multiply(bigTenToThe(n - 1)); + } else { + BigInteger tmp = bigTenToThe(n/2); + return tmp.multiply(tmp); + } } /** diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java index f5ff211f8d4..88b17406799 100644 --- a/jdk/src/share/classes/java/util/Base64.java +++ b/jdk/src/share/classes/java/util/Base64.java @@ -64,7 +64,8 @@ import java.nio.charset.StandardCharsets; * RFC 2045 for encoding and decoding operation. The encoded output * must be represented in lines of no more than 76 characters each * and uses a carriage return {@code '\r'} followed immediately by - * a linefeed {@code '\n'} as the line separator. All line separators + * a linefeed {@code '\n'} as the line separator. No line separator + * is added to the end of the encoded output. All line separators * or other characters not found in the base64 alphabet table are * ignored in decoding operation.

* @@ -413,6 +414,7 @@ public class Base64 { * specified Base64 encoded format */ public OutputStream wrap(OutputStream os) { + Objects.requireNonNull(os); return new EncOutputStream(os, isURL ? toBase64URL : toBase64, newline, linemax); } @@ -613,6 +615,13 @@ public class Base64 { * This class implements a decoder for decoding byte data using the * Base64 encoding scheme as specified in RFC 4648 and RFC 2045. * + *

The Base64 padding character {@code '='} is accepted and + * interpreted as the end of the encoded byte data, but is not + * required. So if the final unit of the encoded byte data only has + * two or three Base64 characters (without the corresponding padding + * character(s) padded), they are decoded as if followed by padding + * character(s). + * *

Instances of {@link Decoder} class are safe for use by * multiple concurrent threads. * @@ -695,7 +704,7 @@ public class Base64 { * using the {@link Base64} encoding scheme. * *

An invocation of this method has exactly the same effect as invoking - * {@code return decode(src.getBytes(StandardCharsets.ISO_8859_1))} + * {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))} * * @param src * the string to decode @@ -856,6 +865,9 @@ public class Base64 { /** * Returns an input stream for decoding {@link Base64} encoded byte stream. * + *

The {@code read} methods of the returned {@code InputStream} will + * throw {@code IOException} when reading bytes that cannot be decoded. + * *

Closing the returned input stream will close the underlying * input stream. * @@ -866,6 +878,7 @@ public class Base64 { * byte stream */ public InputStream wrap(InputStream is) { + Objects.requireNonNull(is); return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME); } @@ -881,13 +894,16 @@ public class Base64 { int dl = dst.arrayOffset() + dst.limit(); int dp0 = dp; int mark = sp; - boolean padding = false; try { while (sp < sl) { int b = sa[sp++] & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte - padding = true; + if (shiftto == 6 && (sp == sl || sa[sp++] != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -913,24 +929,23 @@ public class Base64 { if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; - if (padding && (sp + 1 != sl || sa[sp++] != '=')) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); da[dp++] = (byte)(bits >> 16); - mark = sp; } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); da[dp++] = (byte)(bits >> 16); da[dp++] = (byte)(bits >> 8); - mark = sp; - } else if (padding || shiftto != 18) { + } else if (shiftto == 12) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } + while (sp < sl) { + if (isMIME && base64[sa[sp++]] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + mark = sp; return dp - dp0; } finally { src.position(mark); @@ -948,14 +963,16 @@ public class Base64 { int dl = dst.limit(); int dp0 = dp; int mark = sp; - boolean padding = false; - try { while (sp < sl) { int b = src.get(sp++) & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte - padding = true; + if (shiftto == 6 && (sp == sl || src.get(sp++) != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -981,24 +998,23 @@ public class Base64 { if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; - if (padding && (sp + 1 != sl || src.get(sp++) != '=')) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); dst.put(dp++, (byte)(bits >> 16)); - mark = sp; } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); dst.put(dp++, (byte)(bits >> 16)); dst.put(dp++, (byte)(bits >> 8)); - mark = sp; - } else if (padding || shiftto != 18) { + } else if (shiftto == 12) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } + while (sp < sl) { + if (isMIME && base64[src.get(sp++)] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + mark = sp; return dp - dp0; } finally { src.position(mark); @@ -1012,9 +1028,12 @@ public class Base64 { int len = sl - sp; if (len == 0) return 0; - if (len < 2) + if (len < 2) { + if (isMIME && base64[0] == -1) + return 0; throw new IllegalArgumentException( "Input byte[] should at least have 2 bytes for base64 bytes"); + } if (src[sl - 1] == '=') { paddings++; if (src[sl - 2] == '=') @@ -1043,12 +1062,20 @@ public class Base64 { int dp = 0; int bits = 0; int shiftto = 18; // pos of first byte of 4-byte atom - boolean padding = false; while (sp < sl) { int b = src[sp++] & 0xff; if ((b = base64[b]) < 0) { - if (b == -2) { // padding byte - padding = true; + if (b == -2) { // padding byte '=' + // xx= shiftto==6&&sp==sl missing last = + // xx=y shiftto==6 last is not = + // = shiftto==18 unnecessary padding + // x= shiftto==12 be taken care later + // together with single x, invalid anyway + if (shiftto == 6 && (sp == sl || src[sp++] != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -1068,22 +1095,23 @@ public class Base64 { bits = 0; } } - // reach end of byte arry or hit padding '=' characters. - // if '=' presents, they must be the last one or two. - if (shiftto == 6) { // xx== - if (padding && (sp + 1 != sl || src[sp] != '=')) - throw new IllegalArgumentException( - "Input byte array has wrong 4-byte ending unit"); + // reached end of byte array or hit padding '=' characters. + if (shiftto == 6) { dst[dp++] = (byte)(bits >> 16); - } else if (shiftto == 0) { // xxx= - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input byte array has wrong 4-byte ending unit"); + } else if (shiftto == 0) { dst[dp++] = (byte)(bits >> 16); dst[dp++] = (byte)(bits >> 8); - } else if (padding || shiftto != 18) { - throw new IllegalArgumentException( - "last unit does not have enough bytes"); + } else if (shiftto == 12) { + throw new IllegalArgumentException( + "Last unit does not have enough valid bits"); + } + // anything left is invalid, if is not MIME. + // if MIME, ignore all non-base64 character + while (sp < sl) { + if (isMIME && base64[src[sp++]] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); } return dp; } @@ -1247,8 +1275,22 @@ public class Base64 { int v = is.read(); if (v == -1) { eof = true; - if (nextin != 18) - throw new IOException("Base64 stream has un-decoded dangling byte(s)."); + if (nextin != 18) { + if (nextin == 12) + throw new IOException("Base64 stream has one un-decoded dangling byte."); + // treat ending xx/xxx without padding character legal. + // same logic as v == 'v' below + b[off++] = (byte)(bits >> (16)); + len--; + if (nextin == 0) { // only one padding byte + if (len == 0) { // no enough output space + bits >>= 8; // shift to lowest byte + nextout = 0; + } else { + b[off++] = (byte) (bits >> 8); + } + } + } if (off == oldOff) return -1; else diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java index f5f479588c1..03a58004918 100644 --- a/jdk/src/share/classes/java/util/Formatter.java +++ b/jdk/src/share/classes/java/util/Formatter.java @@ -351,7 +351,9 @@ import sun.misc.FormattedFloatingDecimal; * {@code 'a'}, {@code 'A'} * floating point * The result is formatted as a hexadecimal floating-point number with - * a significand and an exponent + * a significand and an exponent. This conversion is not supported + * for the {@code BigDecimal} type despite the latter's being in the + * floating point argument category. * * {@code 't'}, {@code 'T'} * date/time diff --git a/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java b/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java index c130068612e..5a01e000790 100644 --- a/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java +++ b/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,12 +103,12 @@ public class PixelToShapeConverter GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD); if (nPoints > 0) { gp.moveTo(xPoints[0], yPoints[0]); - } - for (int i = 1; i < nPoints; i++) { - gp.lineTo(xPoints[i], yPoints[i]); - } - if (close) { - gp.closePath(); + for (int i = 1; i < nPoints; i++) { + gp.lineTo(xPoints[i], yPoints[i]); + } + if (close) { + gp.closePath(); + } } return gp; } diff --git a/jdk/src/share/classes/sun/management/Agent.java b/jdk/src/share/classes/sun/management/Agent.java index 19d2dedb5b4..feef02ad6be 100644 --- a/jdk/src/share/classes/sun/management/Agent.java +++ b/jdk/src/share/classes/sun/management/Agent.java @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package sun.management; import java.io.BufferedInputStream; @@ -31,49 +30,55 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; - +import java.lang.management.ManagementFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.management.ManagementFactory; - +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; import java.text.MessageFormat; - import java.util.MissingResourceException; import java.util.Properties; import java.util.ResourceBundle; import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXServiceURL; import static sun.management.AgentConfigurationError.*; import sun.management.jmxremote.ConnectorBootstrap; +import sun.management.jdp.JdpController; +import sun.management.jdp.JdpException; import sun.misc.VMSupport; /** - * This Agent is started by the VM when -Dcom.sun.management.snmp - * or -Dcom.sun.management.jmxremote is set. This class will be - * loaded by the system class loader. Also jmx framework could - * be started by jcmd + * This Agent is started by the VM when -Dcom.sun.management.snmp or + * -Dcom.sun.management.jmxremote is set. This class will be loaded by the + * system class loader. Also jmx framework could be started by jcmd */ public class Agent { // management properties + private static Properties mgmtProps; private static ResourceBundle messageRB; - private static final String CONFIG_FILE = - "com.sun.management.config.file"; + "com.sun.management.config.file"; private static final String SNMP_PORT = - "com.sun.management.snmp.port"; + "com.sun.management.snmp.port"; private static final String JMXREMOTE = - "com.sun.management.jmxremote"; + "com.sun.management.jmxremote"; private static final String JMXREMOTE_PORT = - "com.sun.management.jmxremote.port"; + "com.sun.management.jmxremote.port"; + private static final String RMI_PORT = + "com.sun.management.jmxremote.rmi.port"; private static final String ENABLE_THREAD_CONTENTION_MONITORING = - "com.sun.management.enableThreadContentionMonitoring"; + "com.sun.management.enableThreadContentionMonitoring"; private static final String LOCAL_CONNECTOR_ADDRESS_PROP = - "com.sun.management.jmxremote.localConnectorAddress"; - + "com.sun.management.jmxremote.localConnectorAddress"; private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME = - "sun.management.snmp.AdaptorBootstrap"; + "sun.management.snmp.AdaptorBootstrap"; + + private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225"; + private static final int JDP_DEFAULT_PORT = 7095; // The only active agent allowed private static JMXConnectorServer jmxServer = null; @@ -81,26 +86,25 @@ public class Agent { // Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy // and return property set if args is null or empty // return empty property set - private static Properties parseString(String args){ + private static Properties parseString(String args) { Properties argProps = new Properties(); if (args != null) { - for (String option : args.split(",")) { - String s[] = option.split("=", 2); - String name = s[0].trim(); - String value = (s.length > 1) ? s[1].trim() : ""; + for (String option : args.split(",")) { + String s[] = option.split("=", 2); + String name = s[0].trim(); + String value = (s.length > 1) ? s[1].trim() : ""; - if (!name.startsWith("com.sun.management.")) { - error(INVALID_OPTION, name); - } + if (!name.startsWith("com.sun.management.")) { + error(INVALID_OPTION, name); + } - argProps.setProperty(name, value); - } + argProps.setProperty(name, value); + } } return argProps; } - // invoked by -javaagent or -Dcom.sun.management.agent.class public static void premain(String args) throws Exception { agentmain(args); @@ -115,18 +119,18 @@ public class Agent { Properties arg_props = parseString(args); // Read properties from the config file - Properties config_props = new Properties(); - String fname = arg_props.getProperty(CONFIG_FILE); - readConfiguration(fname, config_props); + Properties config_props = new Properties(); + String fname = arg_props.getProperty(CONFIG_FILE); + readConfiguration(fname, config_props); - // Arguments override config file - config_props.putAll(arg_props); - startAgent(config_props); + // Arguments override config file + config_props.putAll(arg_props); + startAgent(config_props); } // jcmd ManagementAgent.start_local entry point // Also called due to command-line via startAgent() - private static synchronized void startLocalManagementAgent(){ + private static synchronized void startLocalManagementAgent() { Properties agentProps = VMSupport.getAgentProperties(); // start local connector if not started @@ -156,7 +160,7 @@ public class Agent { throw new RuntimeException(getText(INVALID_STATE, "Agent already started")); } - Properties argProps = parseString(args); + Properties argProps = parseString(args); Properties configProps = new Properties(); // Load the management properties from the config file @@ -169,7 +173,7 @@ public class Agent { // management properties can be overridden by system properties // which take precedence Properties sysProps = System.getProperties(); - synchronized(sysProps){ + synchronized (sysProps) { configProps.putAll(sysProps); } @@ -190,21 +194,26 @@ public class Agent { // can specify this property inside config file, so enable optional // monitoring functionality if this property is set final String enableThreadContentionMonitoring = - configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); + configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); if (enableThreadContentionMonitoring != null) { ManagementFactory.getThreadMXBean(). - setThreadContentionMonitoringEnabled(true); + setThreadContentionMonitoringEnabled(true); } String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT); if (jmxremotePort != null) { jmxServer = ConnectorBootstrap. - startRemoteConnectorServer(jmxremotePort, configProps); + startRemoteConnectorServer(jmxremotePort, configProps); + + startDiscoveryService(configProps); } } private static synchronized void stopRemoteManagementAgent() throws Exception { + + JdpController.stopDiscoveryService(); + if (jmxServer != null) { ConnectorBootstrap.unexportRegistry(); @@ -222,15 +231,15 @@ public class Agent { // Enable optional monitoring functionality if requested final String enableThreadContentionMonitoring = - props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); + props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); if (enableThreadContentionMonitoring != null) { ManagementFactory.getThreadMXBean(). - setThreadContentionMonitoringEnabled(true); + setThreadContentionMonitoringEnabled(true); } try { if (snmpPort != null) { - loadSnmpAgent(snmpPort, props); + loadSnmpAgent(snmpPort, props); } /* @@ -242,13 +251,14 @@ public class Agent { * of this "local" server is exported as a counter to the jstat * instrumentation buffer. */ - if (jmxremote != null || jmxremotePort != null) { + if (jmxremote != null || jmxremotePort != null) { if (jmxremotePort != null) { - jmxServer = ConnectorBootstrap. - startRemoteConnectorServer(jmxremotePort, props); + jmxServer = ConnectorBootstrap. + startRemoteConnectorServer(jmxremotePort, props); + startDiscoveryService(props); } startLocalManagementAgent(); - } + } } catch (AgentConfigurationError e) { error(e.getError(), e.getParams()); @@ -257,6 +267,73 @@ public class Agent { } } + private static void startDiscoveryService(Properties props) + throws IOException { + // Start discovery service if requested + String discoveryPort = props.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = props.getProperty("com.sun.management.jdp.address"); + String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery"); + + // Decide whether we should start autodicovery service. + // To start autodiscovery following conditions should be met: + // autodiscovery==true OR (autodicovery==null AND jdp.port != NULL) + + boolean shouldStart = false; + if (discoveryShouldStart == null){ + shouldStart = (discoveryPort != null); + } + else{ + try{ + shouldStart = Boolean.parseBoolean(discoveryShouldStart); + } catch (NumberFormatException e) { + throw new AgentConfigurationError("Couldn't parse autodiscovery argument"); + } + } + + if (shouldStart) { + // port and address are required arguments and have no default values + InetAddress address; + try { + address = (discoveryAddress == null) ? + InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress); + } catch (UnknownHostException e) { + throw new AgentConfigurationError("Unable to broadcast to requested address", e); + } + + int port = JDP_DEFAULT_PORT; + if (discoveryPort != null) { + try { + port = Integer.parseInt(discoveryPort); + } catch (NumberFormatException e) { + throw new AgentConfigurationError("Couldn't parse JDP port argument"); + } + } + + // Rebuilding service URL to broadcast it + String jmxremotePort = props.getProperty(JMXREMOTE_PORT); + String rmiPort = props.getProperty(RMI_PORT); + + JMXServiceURL url = jmxServer.getAddress(); + String hostname = url.getHost(); + + String jmxUrlStr = (rmiPort != null) + ? String.format( + "service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi", + hostname, rmiPort, hostname, jmxremotePort) + : String.format( + "service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", hostname, jmxremotePort); + + String instanceName = System.getProperty("com.sun.management.jdp.name"); + + try{ + JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr); + } + catch(JdpException e){ + throw new AgentConfigurationError("Couldn't start JDP service", e); + } + } + } + public static Properties loadManagementProperties() { Properties props = new Properties(); @@ -268,22 +345,22 @@ public class Agent { // management properties can be overridden by system properties // which take precedence Properties sysProps = System.getProperties(); - synchronized(sysProps){ + synchronized (sysProps) { props.putAll(sysProps); } return props; - } + } - public static synchronized Properties getManagementProperties() { + public static synchronized Properties getManagementProperties() { if (mgmtProps == null) { String configFile = System.getProperty(CONFIG_FILE); String snmpPort = System.getProperty(SNMP_PORT); String jmxremote = System.getProperty(JMXREMOTE); String jmxremotePort = System.getProperty(JMXREMOTE_PORT); - if (configFile == null && snmpPort == null && - jmxremote == null && jmxremotePort == null) { + if (configFile == null && snmpPort == null + && jmxremote == null && jmxremotePort == null) { // return if out-of-the-management option is not specified return null; } @@ -297,22 +374,23 @@ public class Agent { // invoke the following through reflection: // AdaptorBootstrap.initialize(snmpPort, props); final Class adaptorClass = - Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME,true,null); + Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME, true, null); final Method initializeMethod = adaptorClass.getMethod("initialize", - String.class, Properties.class); - initializeMethod.invoke(null,snmpPort,props); + String.class, Properties.class); + initializeMethod.invoke(null, snmpPort, props); } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) { // snmp runtime doesn't exist - initialization fails - throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x); + throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, x); } catch (InvocationTargetException x) { final Throwable cause = x.getCause(); - if (cause instanceof RuntimeException) + if (cause instanceof RuntimeException) { throw (RuntimeException) cause; - else if (cause instanceof Error) + } else if (cause instanceof Error) { throw (Error) cause; + } // should not happen... - throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,cause); + throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, cause); } } @@ -353,8 +431,8 @@ public class Agent { } catch (IOException e) { error(CONFIG_FILE_CLOSE_FAILED, fname); } - } - } + } + } } public static void startAgent() throws Exception { @@ -389,9 +467,9 @@ public class Agent { // invoke the premain(String args) method Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); Method premain = clz.getMethod("premain", - new Class[] { String.class }); + new Class[]{String.class}); premain.invoke(null, /* static */ - new Object[] { args }); + new Object[]{args}); } catch (ClassNotFoundException ex) { error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\""); } catch (NoSuchMethodException ex) { @@ -400,8 +478,8 @@ public class Agent { error(AGENT_CLASS_ACCESS_DENIED); } catch (Exception ex) { String msg = (ex.getCause() == null - ? ex.getMessage() - : ex.getCause().getMessage()); + ? ex.getMessage() + : ex.getCause().getMessage()); error(AGENT_CLASS_FAILED, msg); } } @@ -425,7 +503,6 @@ public class Agent { } } - public static void error(String key, String message) { String keyText = getText(key); System.err.print(getText("agent.err.error") + ": " + keyText); @@ -447,7 +524,7 @@ public class Agent { private static void initResource() { try { messageRB = - ResourceBundle.getBundle("sun.management.resources.agent"); + ResourceBundle.getBundle("sun.management.resources.agent"); } catch (MissingResourceException e) { throw new Error("Fatal: Resource for management agent is missing"); } @@ -470,10 +547,9 @@ public class Agent { } String format = messageRB.getString(key); if (format == null) { - format = "missing resource key: key = \"" + key + "\", " + - "arguments = \"{0}\", \"{1}\", \"{2}\""; + format = "missing resource key: key = \"" + key + "\", " + + "arguments = \"{0}\", \"{1}\", \"{2}\""; } return MessageFormat.format(format, (Object[]) args); } - } diff --git a/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java new file mode 100644 index 00000000000..df5f23458e5 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.management.jdp; + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.UnsupportedAddressTypeException; + +/** + * JdpBroadcaster is responsible for sending pre-built JDP packet across a Net + * + *

Multicast group address, port number and ttl have to be chosen on upper + * level and passed to broadcaster constructor. Also it's possible to specify + * source address to broadcast from.

+ * + *

JdpBradcaster doesn't perform any validation on a supplied {@code port} and {@code ttl} because + * the allowed values depend on an operating system setup

+ * + */ +public final class JdpBroadcaster { + + private final InetAddress addr; + private final int port; + private final DatagramChannel channel; + + /** + * Create a new broadcaster + * + * @param address - multicast group address + * @param srcAddress - address of interface we should use to broadcast. + * @param port - udp port to use + * @param ttl - packet ttl + * @throws IOException + */ + public JdpBroadcaster(InetAddress address, InetAddress srcAddress, int port, int ttl) + throws IOException, JdpException { + this.addr = address; + this.port = port; + + ProtocolFamily family = (address instanceof Inet6Address) + ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + + channel = DatagramChannel.open(family); + channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); + channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl); + + // with srcAddress equal to null, this constructor do exactly the same as + // if srcAddress is not passed + if (srcAddress != null) { + // User requests particular interface to bind to + NetworkInterface interf = NetworkInterface.getByInetAddress(srcAddress); + try { + channel.bind(new InetSocketAddress(srcAddress, 0)); + } catch (UnsupportedAddressTypeException ex) { + throw new JdpException("Unable to bind to source address"); + } + channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, interf); + } + } + + /** + * Create a new broadcaster + * + * @param address - multicast group address + * @param port - udp port to use + * @param ttl - packet ttl + * @throws IOException + */ + public JdpBroadcaster(InetAddress address, int port, int ttl) + throws IOException, JdpException { + this(address, null, port, ttl); + } + + /** + * Broadcast pre-built packet + * + * @param packet - instance of JdpPacket + * @throws IOException + */ + public void sendPacket(JdpPacket packet) + throws IOException { + byte[] data = packet.getPacketData(); + // Unlike allocate/put wrap don't need a flip afterward + ByteBuffer b = ByteBuffer.wrap(data); + channel.send(b, new InetSocketAddress(addr, port)); + } + + /** + * Shutdown broadcaster and close underlying socket channel + * + * @throws IOException + */ + public void shutdown() throws IOException { + channel.close(); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpController.java b/jdk/src/share/classes/sun/management/jdp/JdpController.java new file mode 100644 index 00000000000..d8d0ed46930 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpController.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.management.jdp; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.UUID; + +/** + * JdpController is responsible to create and manage a broadcast loop + * + *

Other part of code has no access to broadcast loop and have to use + * provided static methods + * {@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} + * and {@link #stopDiscoveryService() stopDiscoveryService}

+ *

{@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} could be called multiple + * times as it stops the running service if it is necessary. Call to {@link #stopDiscoveryService() stopDiscoveryService} + * ignored if service isn't run

+ * + * + *

+ * + *

System properties below could be used to control broadcast loop behavior. + * Property below have to be set explicitly in command line. It's not possible to + * set it in management.config file. Careless changes of these properties could + * lead to security or network issues. + *

    + *
  • com.sun.management.jdp.ttl - set ttl for broadcast packet
  • + *
  • com.sun.management.jdp.pause - set broadcast interval in seconds
  • + *
  • com.sun.management.jdp.source_addr - an address of interface to use for broadcast
  • + *
+

+ *

null parameters values are filtered out on {@link JdpPacketWriter} level and + * corresponding keys are not placed to packet.

+ */ +public final class JdpController { + + private static class JDPControllerRunner implements Runnable { + + private final JdpJmxPacket packet; + private final JdpBroadcaster bcast; + private final int pause; + private volatile boolean shutdown = false; + + private JDPControllerRunner(JdpBroadcaster bcast, JdpJmxPacket packet, int pause) { + this.bcast = bcast; + this.packet = packet; + this.pause = pause; + } + + @Override + public void run() { + try { + while (!shutdown) { + bcast.sendPacket(packet); + try { + Thread.sleep(this.pause); + } catch (InterruptedException e) { + // pass + } + } + + } catch (IOException e) { + // pass; + } + + // It's not possible to re-use controller, + // nevertheless reset shutdown variable + try { + stop(); + bcast.shutdown(); + } catch (IOException ex) { + // pass - ignore IOException during shutdown + } + } + + public void stop() { + shutdown = true; + } + } + private static JDPControllerRunner controller = null; + + private JdpController(){ + // Don't allow to instantiate this class. + } + + // Utility to handle optional system properties + // Parse an integer from string or return default if provided string is null + private static int getInteger(String val, int dflt, String msg) throws JdpException { + try { + return (val == null) ? dflt : Integer.parseInt(val); + } catch (NumberFormatException ex) { + throw new JdpException(msg); + } + } + + // Parse an inet address from string or return default if provided string is null + private static InetAddress getInetAddress(String val, InetAddress dflt, String msg) throws JdpException { + try { + return (val == null) ? dflt : InetAddress.getByName(val); + } catch (UnknownHostException ex) { + throw new JdpException(msg); + } + } + + /** + * Starts discovery service + * + * @param address - multicast group address + * @param port - udp port to use + * @param instanceName - name of running JVM instance + * @param url - JMX service url + * @throws IOException + */ + public static synchronized void startDiscoveryService(InetAddress address, int port, String instanceName, String url) + throws IOException, JdpException { + + // Limit packet to local subnet by default + int ttl = getInteger( + System.getProperty("com.sun.management.jdp.ttl"), 1, + "Invalid jdp packet ttl"); + + // Broadcast once a 5 seconds by default + int pause = getInteger( + System.getProperty("com.sun.management.jdp.pause"), 5, + "Invalid jdp pause"); + + // Converting seconds to milliseconds + pause = pause * 1000; + + // Allow OS to choose broadcast source + InetAddress sourceAddress = getInetAddress( + System.getProperty("com.sun.management.jdp.source_addr"), null, + "Invalid source address provided"); + + // Generate session id + UUID id = UUID.randomUUID(); + + JdpJmxPacket packet = new JdpJmxPacket(id, url); + + // Don't broadcast whole command line for security reason. + // Strip everything after first space + String javaCommand = System.getProperty("sun.java.command"); + if (javaCommand != null) { + String[] arr = javaCommand.split(" ", 2); + packet.setMainClass(arr[0]); + } + + // Put optional explicit java instance name to packet, if user doesn't specify + // it the key is skipped. PacketWriter is responsible to skip keys having null value. + packet.setInstanceName(instanceName); + + JdpBroadcaster bcast = new JdpBroadcaster(address, sourceAddress, port, ttl); + + // Stop discovery service if it's already running + stopDiscoveryService(); + + controller = new JDPControllerRunner(bcast, packet, pause); + + Thread t = new Thread(controller, "JDP broadcaster"); + t.setDaemon(true); + t.start(); + } + + /** + * Stop running discovery service, + * it's safe to attempt to stop not started service + */ + public static synchronized void stopDiscoveryService() { + if ( controller != null ){ + controller.stop(); + controller = null; + } + } +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java b/jdk/src/share/classes/sun/management/jdp/JdpException.java similarity index 73% rename from langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java rename to jdk/src/share/classes/sun/management/jdp/JdpException.java index 5067ef20625..03404223e94 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpException.java @@ -20,23 +20,21 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package sun.management.jdp; /** - * @test - * @summary Smoke test for repeating annotations - * @compile/fail UseWrongContainerFor.java - * @bug 7151010 + * An Exception thrown if a JDP implementation encounters a problem. */ +public final class JdpException extends Exception { -import java.lang.annotation.*; + private static final long serialVersionUID = 1L; -@ContainerFor(Retention.class) -@interface Foos { - UseWrongContainerFor[] value(); + /** + * Construct a new JDP exception with a meaningful message + * + * @param msg - message + */ + public JdpException(String msg) { + super(msg); + } } - -@ContainedBy(Foos.class) -public @interface UseWrongContainerFor {} - -@UseWrongContainerFor @UseWrongContainerFor -@interface Foo {} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java new file mode 100644 index 00000000000..8e88b148265 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.management.jdp; + +/** + * JdpGenericPacket responsible to provide fields + * common for all Jdp packets + */ +public abstract class JdpGenericPacket implements JdpPacket { + + /** + * JDP protocol magic. Magic allows a reader to quickly select + * JDP packets from a bunch of broadcast packets addressed to the same port + * and broadcast group. Any packet intended to be parsed by JDP client + * has to start from this magic. + */ + private static final int MAGIC = 0xC0FFEE42; + + /** + * Current version of protocol. Any implementation of this protocol has to + * conform with the packet structure and the flow described in JEP-168 + */ + private static final short PROTOCOL_VERSION = 1; + + /** + * Default do-nothing constructor + */ + protected JdpGenericPacket(){ + // do nothing + } + + + /** + * Validate protocol header magic field + * + * @param magic - value to validate + * @throws JdpException + */ + public static void checkMagic(int magic) + throws JdpException { + if (magic != MAGIC) { + throw new JdpException("Invalid JDP magic header: " + magic); + } + } + + /** + * Validate protocol header version field + * + * @param version - value to validate + * @throws JdpException + */ + public static void checkVersion(short version) + throws JdpException { + + if (version > PROTOCOL_VERSION) { + throw new JdpException("Unsupported protocol version: " + version); + } + } + + /** + * + * @return protocol magic + */ + public static int getMagic() { + return MAGIC; + } + + /** + * + * @return current protocol version + */ + public static short getVersion() { + return PROTOCOL_VERSION; + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java new file mode 100644 index 00000000000..7d5ccc2f892 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.management.jdp; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; + +/** + * A packet to broadcasts JMX URL + * + * Fields: + * + *
    + *
  • UUID - broadcast session ID, changed every time when we start/stop + * discovery service
  • + *
  • JMX_URL - URL to connect to JMX service
  • + *
  • MAIN_CLASS - optional name of main class, filled from sun.java.command stripped for + * security reason to first space
  • + *
  • INSTANCE_NAME - optional custom name of particular instance as provided by customer
  • + *
+ */ +public final class JdpJmxPacket + extends JdpGenericPacket + implements JdpPacket { + + /** + * Session ID + */ + public final static String UUID_KEY = "DISCOVERABLE_SESSION_UUID"; + /** + * Name of main class + */ + public final static String MAIN_CLASS_KEY = "MAIN_CLASS"; + /** + * JMX service URL + */ + public final static String JMX_SERVICE_URL_KEY = "JMX_SERVICE_URL"; + /** + * Name of Java instance + */ + public final static String INSTANCE_NAME_KEY = "INSTANCE_NAME"; + + private UUID id; + private String mainClass; + private String jmxServiceUrl; + private String instanceName; + + /** + * Create new instance from user provided data. Set mandatory fields + * + * @param id - java instance id + * @param jmxServiceUrl - JMX service url + */ + public JdpJmxPacket(UUID id, String jmxServiceUrl) { + this.id = id; + this.jmxServiceUrl = jmxServiceUrl; + } + + /** + * Create new instance from network data Parse packet and set fields. + * + * @param data - raw packet data as it came from a Net + * @throws JdpException + */ + public JdpJmxPacket(byte[] data) + throws JdpException { + JdpPacketReader reader; + + reader = new JdpPacketReader(data); + Map p = reader.getDiscoveryDataAsMap(); + + String sId = p.get(UUID_KEY); + this.id = (sId == null) ? null : UUID.fromString(sId); + this.jmxServiceUrl = p.get(JMX_SERVICE_URL_KEY); + this.mainClass = p.get(MAIN_CLASS_KEY); + this.instanceName = p.get(INSTANCE_NAME_KEY); + } + + /** + * Set main class field + * + * @param mainClass - main class of running app + */ + public void setMainClass(String mainClass) { + this.mainClass = mainClass; + } + + /** + * Set instance name field + * + * @param instanceName - name of instance as provided by customer + */ + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + /** + * @return id of discovery session + */ + public UUID getId() { + return id; + } + + /** + * + * @return main class field + */ + public String getMainClass() { + return mainClass; + } + + /** + * + * @return JMX service URL + */ + public String getJmxServiceUrl() { + return jmxServiceUrl; + } + + /** + * + * @return instance name + */ + public String getInstanceName() { + return instanceName; + } + + /** + * + * @return assembled packet ready to be sent across a Net + * @throws IOException + */ + @Override + public byte[] getPacketData() throws IOException { + // Assemble packet from fields to byte array + JdpPacketWriter writer; + writer = new JdpPacketWriter(); + writer.addEntry(UUID_KEY, (id == null) ? null : id.toString()); + writer.addEntry(MAIN_CLASS_KEY, mainClass); + writer.addEntry(JMX_SERVICE_URL_KEY, jmxServiceUrl); + writer.addEntry(INSTANCE_NAME_KEY, instanceName); + return writer.getPacketBytes(); + } + + /** + * + * @return packet hash code + */ + @Override + public int hashCode() { + int hash = 1; + hash = hash * 31 + id.hashCode(); + hash = hash * 31 + jmxServiceUrl.hashCode(); + return hash; + } + + /** + * Compare two packets + * + * @param o - packet to compare + * @return either packet equals or not + */ + @Override + public boolean equals(Object o) { + + if (o == null || ! (o instanceof JdpJmxPacket) ){ + return false; + } + + JdpJmxPacket p = (JdpJmxPacket) o; + return Objects.equals(id, p.getId()) && Objects.equals(jmxServiceUrl, p.getJmxServiceUrl()); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java new file mode 100644 index 00000000000..ba0ec4f97ac --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.management.jdp; + +import java.io.IOException; + +/** + * Packet to broadcast + * + *

Each packet have to contain MAGIC and PROTOCOL_VERSION in order to be + * recognized as a valid JDP packet.

+ * + *

Default implementation build packet as a set of UTF-8 encoded Key/Value pairs + * are stored as an ordered list of values, and are sent to the server + * in that order.

+ * + *

+ * Packet structure: + * + * 4 bytes JDP magic (0xC0FFE42) + * 2 bytes JDP protocol version (01) + * + * 2 bytes size of key + * x bytes key (UTF-8 encoded) + * 2 bytes size of value + * x bytes value (UTF-8 encoded) + * + * repeat as many times as necessary ... + *

+ */ +public interface JdpPacket { + + /** + * This method responsible to assemble packet and return a byte array + * ready to be sent across a Net. + * + * @return assembled packet as an array of bytes + * @throws IOException + */ + public byte[] getPacketData() throws IOException; + +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java new file mode 100644 index 00000000000..9f3957ab5ce --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.management.jdp; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * JdpPacketReader responsible for reading a packet

This class gets a byte + * array as it came from a Net, validates it and breaks a part

+ */ +public final class JdpPacketReader { + + private final DataInputStream pkt; + private Map pmap = null; + + /** + * Create packet reader, extract and check magic and version + * + * @param packet - packet received from a Net + * @throws JdpException + */ + public JdpPacketReader(byte[] packet) + throws JdpException { + ByteArrayInputStream bais = new ByteArrayInputStream(packet); + pkt = new DataInputStream(bais); + + try { + int magic = pkt.readInt(); + JdpGenericPacket.checkMagic(magic); + } catch (IOException e) { + throw new JdpException("Invalid JDP packet received, bad magic"); + } + + try { + short version = pkt.readShort(); + JdpGenericPacket.checkVersion(version); + } catch (IOException e) { + throw new JdpException("Invalid JDP packet received, bad protocol version"); + } + } + + /** + * Get next entry from packet + * + * @return the entry + * @throws EOFException + * @throws JdpException + */ + public String getEntry() + throws EOFException, JdpException { + + try { + short len = pkt.readShort(); + // Artificial setting the "len" field to Short.MAX_VALUE may cause a reader to allocate + // to much memory. Prevent this possible DOS attack. + if (len < 1 && len > pkt.available()) { + throw new JdpException("Broken JDP packet. Invalid entry length field."); + } + + byte[] b = new byte[len]; + if (pkt.read(b) != len) { + throw new JdpException("Broken JDP packet. Unable to read entry."); + } + return new String(b, "UTF-8"); + + } catch (EOFException e) { + throw e; + } catch (UnsupportedEncodingException ex) { + throw new JdpException("Broken JDP packet. Unable to decode entry."); + } catch (IOException e) { + throw new JdpException("Broken JDP packet. Unable to read entry."); + } + + + } + + /** + * return packet content as a key/value map + * + * @return map containing packet entries pair of entries treated as + * key,value + * @throws IOException + * @throws JdpException + */ + public Map getDiscoveryDataAsMap() + throws JdpException { + // return cached map if possible + if (pmap != null) { + return pmap; + } + + String key = null, value = null; + + final Map tmpMap = new HashMap<>(); + try { + while (true) { + key = getEntry(); + value = getEntry(); + tmpMap.put(key, value); + } + } catch (EOFException e) { + // EOF reached on reading value, report broken packet + // otherwise ignore it. + if (value == null) { + throw new JdpException("Broken JDP packet. Key without value." + key); + } + } + + pmap = Collections.unmodifiableMap(tmpMap); + return pmap; + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java new file mode 100644 index 00000000000..7ebd002608c --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.management.jdp; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * JdpPacketWriter responsible for writing a packet + *

This class assembles a set of key/value pairs to valid JDP packet, + * ready to be sent across a Net

+ */ +public final class JdpPacketWriter { + + private final ByteArrayOutputStream baos; + private final DataOutputStream pkt; + + /** + * Create a JDP packet, add mandatory magic and version headers + * + * @throws IOException + */ + public JdpPacketWriter() + throws IOException { + baos = new ByteArrayOutputStream(); + pkt = new DataOutputStream(baos); + + pkt.writeInt(JdpGenericPacket.getMagic()); + pkt.writeShort(JdpGenericPacket.getVersion()); + } + + /** + * Put string entry to packet + * + * @param entry - string to put (utf-8 encoded) + * @throws IOException + */ + public void addEntry(String entry) + throws IOException { + pkt.writeShort(entry.length()); + byte[] b = entry.getBytes("UTF-8"); + pkt.write(b); + } + + /** + * Put key/value pair to packet + * + * @param key - key to put (utf-8 encoded) + * @param val - value to put (utf-8 encoded) + * @throws IOException + */ + public void addEntry(String key, String val) + throws IOException { + /* Silently skip key if value is null. + * We don't need to distinguish between key missing + * and key has no value cases + */ + if (val != null) { + addEntry(key); + addEntry(val); + } + } + + /** + * Return assembled packet as a byte array + * + * @return packet bytes + */ + public byte[] getPacketBytes() { + return baos.toByteArray(); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/package-info.java b/jdk/src/share/classes/sun/management/jdp/package-info.java new file mode 100644 index 00000000000..e21e461214f --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/package-info.java @@ -0,0 +1,55 @@ +/** + * Summary + * ------- + * + * Define a lightweight network protocol for discovering running and + * manageable Java processes within a network subnet. + * + * + * Description + * ----------- + * + * The protocol is lightweight multicast based, and works like a beacon, + * broadcasting the JMXService URL needed to connect to the external JMX + * agent if an application is started with appropriate parameters. + * + * The payload is structured like this: + * + * 4 bytes JDP magic (0xC0FFEE42) + * 2 bytes JDP protocol version (1) + * 2 bytes size of the next entry + * x bytes next entry (UTF-8 encoded) + * 2 bytes size of next entry + * ... Rinse and repeat... + * + * The payload will be parsed as even entries being keys, odd entries being + * values. + * + * The standard JDP packet contains four entries: + * + * - `DISCOVERABLE_SESSION_UUID` -- Unique id of the instance; this id changes every time + * the discovery protocol starts and stops + * + * - `MAIN_CLASS` -- The value of the `sun.java.command` property + * + * - `JMX_SERVICE_URL` -- The URL to connect to the JMX agent + * + * - `INSTANCE_NAME` -- The user-provided name of the running instance + * + * The protocol sends packets to 239.255.255.225:7095 by default. + * + * The protocol uses system properties to control it's behaviour: + * - `com.sun.management.jdp.port` -- override default port + * + * - `com.sun.management.jdp.address` -- override default address + * + * - `com.sun.management.jmxremote.autodiscovery` -- whether we should start autodiscovery or + * not. Autodiscovery starts if and only if following conditions are met: (autodiscovery is + * true OR (autodiscovery is not set AND jdp.port is set)) + * + * - `com.sun.management.jdp.ttl` -- set ttl for broadcast packet, default is 1 + * - `com.sun.management.jdp.pause` -- set broadcast interval in seconds default is 5 + * - `com.sun.management.jdp.source_addr` -- an address of interface to use for broadcast + */ + +package sun.management.jdp; diff --git a/jdk/src/share/classes/sun/misc/JavaLangAccess.java b/jdk/src/share/classes/sun/misc/JavaLangAccess.java index 9506194c707..db8d8213179 100644 --- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package sun.misc; import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; import sun.reflect.ConstantPool; import sun.reflect.annotation.AnnotationType; import sun.nio.ch.Interruptible; @@ -46,6 +47,18 @@ public interface JavaLangAccess { */ AnnotationType getAnnotationType(Class klass); + /** + * Get the array of bytes that is the class-file representation + * of this Class' type annotations. + */ + byte[] getRawClassTypeAnnotations(Class klass); + + /** + * Get the array of bytes that is the class-file representation + * of this Executable's type annotations. + */ + byte[] getRawExecutableTypeAnnotations(Executable executable); + /** * Returns the elements of an enum class or null if the * Class object does not represent an enum type; @@ -84,9 +97,4 @@ public interface JavaLangAccess { * Returns the ith StackTraceElement for the given throwable. */ StackTraceElement getStackTraceElement(Throwable t, int i); - - /** - * Returns a directly present annotation. - */ - public
A getDirectDeclaredAnnotation(Class klass, Class anno); } diff --git a/jdk/src/share/classes/sun/reflect/LangReflectAccess.java b/jdk/src/share/classes/sun/reflect/LangReflectAccess.java index fba1d318086..3c3b2757410 100644 --- a/jdk/src/share/classes/sun/reflect/LangReflectAccess.java +++ b/jdk/src/share/classes/sun/reflect/LangReflectAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -81,6 +81,9 @@ public interface LangReflectAccess { public void setConstructorAccessor(Constructor c, ConstructorAccessor accessor); + /** Gets the byte[] that encodes TypeAnnotations on an Executable. */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex); + /** Gets the "slot" field from a Constructor (used for serialization) */ public int getConstructorSlot(Constructor c); diff --git a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java index ea5323b8b9a..de97dfc7001 100644 --- a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java +++ b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -26,6 +26,7 @@ package sun.reflect; import java.lang.reflect.Field; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; @@ -314,6 +315,12 @@ public class ReflectionFactory { return langReflectAccess().copyConstructor(arg); } + /** Gets the byte[] that encodes TypeAnnotations on an executable. + */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return langReflectAccess().getExecutableTypeAnnotationBytes(ex); + } + //-------------------------------------------------------------------------- // // Routines used by serialization diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java new file mode 100644 index 00000000000..e0524e849dc --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -0,0 +1,315 @@ +/* + * Copyright (c) 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 sun.reflect.annotation; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static sun.reflect.annotation.TypeAnnotation.*; + +public class AnnotatedTypeFactory { + /** + * Create an AnnotatedType. + * + * @param type the type this AnnotatedType corresponds to + * @param currentLoc the location this AnnotatedType corresponds to + * @param actualTypeAnnos the type annotations this AnnotatedType has + * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget + * as the AnnotatedType being built + * @param decl the declaration having the type use this AnnotatedType + * corresponds to + */ + public static AnnotatedType buildAnnotatedType(Type type, + LocationInfo currentLoc, + TypeAnnotation[] actualTypeAnnos, + TypeAnnotation[] allOnSameTarget, + AnnotatedElement decl) { + if (type == null) { + return EMPTY_ANNOTATED_TYPE; + } + if (isArray(type)) + return new AnnotatedArrayTypeImpl(type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + if (type instanceof Class) { + return new AnnotatedTypeBaseImpl(type, + addNesting(type, currentLoc), + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof TypeVariable) { + return new AnnotatedTypeVariableImpl((TypeVariable)type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof ParameterizedType) { + return new AnnotatedParameterizedTypeImpl((ParameterizedType)type, + addNesting(type, currentLoc), + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof WildcardType) { + return new AnnotatedWildcardTypeImpl((WildcardType) type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + } + throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen."); + } + + private static LocationInfo addNesting(Type type, LocationInfo addTo) { + if (isArray(type)) + return addTo; + if (type instanceof Class) { + Class clz = (Class)type; + if (clz.getEnclosingClass() == null) + return addTo; + return addNesting(clz.getEnclosingClass(), addTo.pushInner()); + } else if (type instanceof ParameterizedType) { + ParameterizedType t = (ParameterizedType)type; + if (t.getOwnerType() == null) + return addTo; + return addNesting(t.getOwnerType(), addTo.pushInner()); + } + return addTo; + } + + private static boolean isArray(Type t) { + if (t instanceof Class) { + Class c = (Class)t; + if (c.isArray()) + return true; + } else if (t instanceof GenericArrayType) { + return true; + } + return false; + } + + static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION, + new TypeAnnotation[0], new TypeAnnotation[0], null); + + private static class AnnotatedTypeBaseImpl implements AnnotatedType { + private final Type type; + private final AnnotatedElement decl; + private final LocationInfo location; + private final TypeAnnotation[] allOnSameTargetTypeAnnotations; + private final Map, Annotation> annotations; + + AnnotatedTypeBaseImpl(Type type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + this.type = type; + this.decl = decl; + this.location = location; + this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations; + this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations)); + } + + // AnnotatedElement + @Override + public final Annotation[] getAnnotations() { + return getDeclaredAnnotations(); + } + + @Override + public final T getAnnotation(Class annotation) { + return getDeclaredAnnotation(annotation); + } + + @Override + public final T[] getAnnotations(Class annotation) { + return getDeclaredAnnotations(annotation); + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return annotations.values().toArray(new Annotation[0]); + } + + @Override + @SuppressWarnings("unchecked") + public T getDeclaredAnnotation(Class annotation) { + return (T)annotations.get(annotation); + } + + @Override + public T[] getDeclaredAnnotations(Class annotation) { + return AnnotationSupport.getMultipleAnnotations(annotations, annotation); + } + + // AnnotatedType + @Override + public Type getType() { + return type; + } + + // Implementation details + LocationInfo getLocation() { + return location; + } + TypeAnnotation[] getTypeAnnotations() { + return allOnSameTargetTypeAnnotations; + } + AnnotatedElement getDecl() { + return decl; + } + } + + private static class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType { + AnnotatedArrayTypeImpl(Type type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType getAnnotatedGenericComponentType() { + return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(), + getLocation().pushArray(), + getTypeAnnotations(), + getTypeAnnotations(), + getDecl()); + } + + private Type getComponentType() { + Type t = getType(); + if (t instanceof Class) { + Class c = (Class)t; + return c.getComponentType(); + } + return ((GenericArrayType)t).getGenericComponentType(); + } + } + + private static class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable { + AnnotatedTypeVariableImpl(TypeVariable type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType[] getAnnotatedBounds() { + return getTypeVariable().getAnnotatedBounds(); + } + + private TypeVariable getTypeVariable() { + return (TypeVariable)getType(); + } + } + + private static class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedParameterizedType { + AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType[] getAnnotatedActualTypeArguments() { + Type[] arguments = getParameterizedType().getActualTypeArguments(); + AnnotatedType[] res = new AnnotatedType[arguments.length]; + Arrays.fill(res, EMPTY_ANNOTATED_TYPE); + int initialCapacity = getTypeAnnotations().length; + for (int i = 0; i < res.length; i++) { + List l = new ArrayList<>(initialCapacity); + LocationInfo newLoc = getLocation().pushTypeArg((byte)i); + for (TypeAnnotation t : getTypeAnnotations()) + if (t.getLocationInfo().isSameLocationInfo(newLoc)) + l.add(t); + res[i] = buildAnnotatedType(arguments[i], + newLoc, + l.toArray(new TypeAnnotation[0]), + getTypeAnnotations(), + getDecl()); + } + return res; + } + + private ParameterizedType getParameterizedType() { + return (ParameterizedType)getType(); + } + } + + private static class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType { + private final boolean hasUpperBounds; + AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + hasUpperBounds = (type.getLowerBounds().length == 0); + } + + @Override + public AnnotatedType[] getAnnotatedUpperBounds() { + if (!hasUpperBounds()) + return new AnnotatedType[0]; + return getAnnotatedBounds(getWildcardType().getUpperBounds()); + } + + @Override + public AnnotatedType[] getAnnotatedLowerBounds() { + if (hasUpperBounds) + return new AnnotatedType[0]; + return getAnnotatedBounds(getWildcardType().getLowerBounds()); + } + + private AnnotatedType[] getAnnotatedBounds(Type[] bounds) { + AnnotatedType[] res = new AnnotatedType[bounds.length]; + Arrays.fill(res, EMPTY_ANNOTATED_TYPE); + LocationInfo newLoc = getLocation().pushWildcard(); + int initialCapacity = getTypeAnnotations().length; + for (int i = 0; i < res.length; i++) { + List l = new ArrayList<>(initialCapacity); + for (TypeAnnotation t : getTypeAnnotations()) + if (t.getLocationInfo().isSameLocationInfo(newLoc)) + l.add(t); + res[i] = buildAnnotatedType(bounds[i], + newLoc, + l.toArray(new TypeAnnotation[0]), + getTypeAnnotations(), + getDecl()); + } + return res; + } + + private WildcardType getWildcardType() { + return (WildcardType)getType(); + } + + private boolean hasUpperBounds() { + return hasUpperBounds; + } + } +} diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java index 6f26ec368b7..a980a9126ef 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,7 +188,7 @@ public class AnnotationParser { * available at runtime */ @SuppressWarnings("unchecked") - private static Annotation parseAnnotation(ByteBuffer buf, + static Annotation parseAnnotation(ByteBuffer buf, ConstantPool constPool, Class container, boolean exceptionOnMissingAnnotationClass) { diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java index 3046792b161..5ca88f90202 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,63 +27,29 @@ package sun.reflect.annotation; import java.lang.annotation.*; import java.lang.reflect.*; -import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; -import sun.reflect.Reflection; -import sun.misc.JavaLangAccess; public final class AnnotationSupport { - private static final JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess(); - - /** - * Finds and returns _one_ annotation of the type indicated by - * {@code annotationClass} from the {@code Map} {@code - * annotationMap}. Looks into containers of the {@code - * annotationClass} (as specified by an the {@code - * annotationClass} type being meta-annotated with an {@code - * ContainedBy} annotation). - * - * @param annotationMap the {@code Map} used to store annotations and indexed by their type - * @param annotationClass the type of annotation to search for - * - * @return in instance of {@code annotationClass} or {@code null} if none were found - */ - public static A getOneAnnotation(final Map, Annotation> annotationMap, - final Class annotationClass) { - @SuppressWarnings("unchecked") - final A candidate = (A)annotationMap.get(annotationClass); - if (candidate != null) { - return candidate; - } - - final Class containerClass = getContainer(annotationClass); - if (containerClass != null) { - return unpackOne(annotationMap.get(containerClass), annotationClass); - } - - return null; // found none - } - /** * Finds and returns all annotation of the type indicated by * {@code annotationClass} from the {@code Map} {@code * annotationMap}. Looks into containers of the {@code * annotationClass} (as specified by an the {@code * annotationClass} type being meta-annotated with an {@code - * ContainedBy} annotation). + * Repeatable} annotation). * * @param annotationMap the {@code Map} used to store annotations indexed by their type * @param annotationClass the type of annotation to search for * * @return an array of instances of {@code annotationClass} or an empty array if none were found */ - public static A[] getMultipleAnnotations(final Map, Annotation> annotationMap, - final Class annotationClass) { - final ArrayList res = new ArrayList(); + public static A[] getMultipleAnnotations( + final Map, Annotation> annotationMap, + final Class annotationClass) { + final List res = new ArrayList(); @SuppressWarnings("unchecked") final A candidate = (A)annotationMap.get(annotationClass); @@ -101,49 +67,10 @@ public final class AnnotationSupport { return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray); } - /** - * Unpacks the {@code annotationMap} parameter into an array of - * {@code Annotation}s. This method will unpack all repeating - * annotations containers (once). An annotation type is marked as a - * container by meta-annotating it the with the {@code - * ContainerFor} annotation. - * - * @param annotationMap the {@code Map} from where the annotations are unpacked - * - * @return an array of Annotation - */ - public static Annotation[] unpackToArray(Map, Annotation> annotationMap) { - List res = new ArrayList<>(); - for (Map.Entry, Annotation> e : annotationMap.entrySet()) { - Class annotationClass = e.getKey(); - Annotation annotationInstance = e.getValue(); - Class containee = getContainee(e.getKey()); - boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null; - - if (isContainer) { - res.addAll(unpackAll(annotationInstance, containee)); - } else { - res.add(annotationInstance); - } - } - - return res.isEmpty() - ? AnnotationParser.getEmptyAnnotationArray() - : res.toArray(AnnotationParser.getEmptyAnnotationArray()); - } - /** Helper to get the container, or null if none, of an annotation. */ private static Class getContainer(Class annotationClass) { - ContainedBy containerAnnotation = - javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class); - return (containerAnnotation == null) ? null : containerAnnotation.value(); - } - - /** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */ - private static Class getContainee(Class annotationClass) { - ContainerFor containerAnnotation = - javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class); - return (containerAnnotation == null) ? null : containerAnnotation.value(); + Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class); + return (containingAnnotation == null) ? null : containingAnnotation.value(); } /** Reflectively look up and get the returned array from the the @@ -156,14 +83,15 @@ public final class AnnotationSupport { // value element. Get the AnnotationType, get the "value" element // and invoke it to get the contents. - Class containerClass = containerInstance.annotationType(); - AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass); + Class containerClass = containerInstance.annotationType(); + AnnotationType annoType = AnnotationType.getInstance(containerClass); if (annoType == null) throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); Method m = annoType.members().get("value"); if (m == null) - throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); + throw new InvalidContainerAnnotationError(containerInstance + + " is an invalid container for repeating annotations"); m.setAccessible(true); @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException @@ -175,32 +103,11 @@ public final class AnnotationSupport { IllegalArgumentException | // parameters doesn't match InvocationTargetException | // the value method threw an exception ClassCastException e) { // well, a cast failed ... - throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations", - e, - containerInstance, - null); - } - } - - /* Sanity check type of and return the first annotation instance - * of type {@code annotationClass} from {@code - * containerInstance}. - */ - private static A unpackOne(Annotation containerInstance, Class annotationClass) { - if (containerInstance == null) { - return null; - } - - try { - return annotationClass.cast(getValueArray(containerInstance)[0]); - } catch (ArrayIndexOutOfBoundsException | // empty array - ClassCastException | // well, a cast failed ... - NullPointerException e) { // can this NP? for good meassure - throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s", - containerInstance, annotationClass), - e, - containerInstance, - annotationClass); + throw new InvalidContainerAnnotationError( + containerInstance + " is an invalid container for repeating annotations", + e, + containerInstance, + null); } } @@ -208,24 +115,26 @@ public final class AnnotationSupport { * instances of type {@code annotationClass} from {@code * containerInstance}. */ - private static List unpackAll(Annotation containerInstance, Class annotationClass) { + private static List unpackAll(Annotation containerInstance, + Class annotationClass) { if (containerInstance == null) { return Collections.emptyList(); // container not present } try { A[] a = getValueArray(containerInstance); - ArrayList l = new ArrayList<>(a.length); + List l = new ArrayList<>(a.length); for (int i = 0; i < a.length; i++) l.add(annotationClass.cast(a[i])); return l; } catch (ClassCastException | NullPointerException e) { - throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s", - containerInstance, annotationClass), - e, - containerInstance, - annotationClass); + throw new InvalidContainerAnnotationError( + String.format("%s is an invalid container for repeating annotations of type: %s", + containerInstance, annotationClass), + e, + containerInstance, + annotationClass); } } } diff --git a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java new file mode 100644 index 00000000000..c5399725e8b --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 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 sun.reflect.annotation; + +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; +import java.lang.reflect.AnnotatedElement; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * A TypeAnnotation contains all the information needed to transform type + * annotations on declarations in the class file to actual Annotations in + * AnnotatedType instances. + * + * TypeAnnotaions contain a base Annotation, location info (which lets you + * distinguish between '@A Inner.@B Outer' in for example nested types), + * target info and the declaration the TypeAnnotaiton was parsed from. + */ +public class TypeAnnotation { + private final TypeAnnotationTargetInfo targetInfo; + private final LocationInfo loc; + private final Annotation annotation; + private final AnnotatedElement baseDeclaration; + + public TypeAnnotation(TypeAnnotationTargetInfo targetInfo, + LocationInfo loc, + Annotation annotation, + AnnotatedElement baseDeclaration) { + this.targetInfo = targetInfo; + this.loc = loc; + this.annotation = annotation; + this.baseDeclaration = baseDeclaration; + } + + public TypeAnnotationTargetInfo getTargetInfo() { + return targetInfo; + } + public Annotation getAnnotation() { + return annotation; + } + public AnnotatedElement getBaseDeclaration() { + return baseDeclaration; + } + public LocationInfo getLocationInfo() { + return loc; + } + + public static List filter(TypeAnnotation[] typeAnnotations, + TypeAnnotationTarget predicate) { + ArrayList typeAnnos = new ArrayList<>(typeAnnotations.length); + for (TypeAnnotation t : typeAnnotations) + if (t.getTargetInfo().getTarget() == predicate) + typeAnnos.add(t); + typeAnnos.trimToSize(); + return typeAnnos; + } + + public static enum TypeAnnotationTarget { + CLASS_TYPE_PARAMETER, + METHOD_TYPE_PARAMETER, + CLASS_EXTENDS, + CLASS_IMPLEMENTS, + CLASS_PARAMETER_BOUND, + METHOD_PARAMETER_BOUND, + METHOD_RETURN_TYPE, + METHOD_RECEIVER_TYPE, + FIELD_TYPE, + THROWS; + } + public static class TypeAnnotationTargetInfo { + private final TypeAnnotationTarget target; + private final int count; + private final int secondaryIndex; + private static final int UNUSED_INDEX = -2; // this is not a valid index in the 308 spec + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target) { + this(target, UNUSED_INDEX, UNUSED_INDEX); + } + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target, + int count) { + this(target, count, UNUSED_INDEX); + } + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target, + int count, + int secondaryIndex) { + this.target = target; + this.count = count; + this.secondaryIndex = secondaryIndex; + } + + public TypeAnnotationTarget getTarget() { + return target; + } + public int getCount() { + return count; + } + public int getSecondaryIndex() { + return secondaryIndex; + } + + @Override + public String toString() { + return "" + target + ": " + count + ", " + secondaryIndex; + } + } + + public static class LocationInfo { + private final int depth; + private final Location[] locations; + + private LocationInfo() { + this(0, new Location[0]); + } + private LocationInfo(int depth, Location[] locations) { + this.depth = depth; + this.locations = locations; + } + + public static final LocationInfo BASE_LOCATION = new LocationInfo(); + + public static LocationInfo parseLocationInfo(ByteBuffer buf) { + int depth = buf.get(); + if (depth == 0) + return BASE_LOCATION; + Location[] locations = new Location[depth]; + for (int i = 0; i < depth; i++) { + byte tag = buf.get(); + byte index = buf.get(); + if (!(tag == 0 || tag == 1 | tag == 2 || tag == 3)) + throw new AnnotationFormatError("Bad Location encoding in Type Annotation"); + if (tag != 3 && index != 0) + throw new AnnotationFormatError("Bad Location encoding in Type Annotation"); + locations[i] = new Location(tag, index); + } + return new LocationInfo(depth, locations); + } + + public LocationInfo pushArray() { + return pushLocation((byte)0, (byte)0); + } + + public LocationInfo pushInner() { + return pushLocation((byte)1, (byte)0); + } + + public LocationInfo pushWildcard() { + return pushLocation((byte) 2, (byte) 0); + } + + public LocationInfo pushTypeArg(byte index) { + return pushLocation((byte) 3, index); + } + + public LocationInfo pushLocation(byte tag, byte index) { + int newDepth = this.depth + 1; + Location[] res = new Location[newDepth]; + System.arraycopy(this.locations, 0, res, 0, depth); + res[newDepth - 1] = new Location(tag, index); + return new LocationInfo(newDepth, res); + } + + public TypeAnnotation[] filter(TypeAnnotation[] ta) { + ArrayList l = new ArrayList<>(ta.length); + for (TypeAnnotation t : ta) { + if (isSameLocationInfo(t.getLocationInfo())) + l.add(t); + } + return l.toArray(new TypeAnnotation[0]); + } + + boolean isSameLocationInfo(LocationInfo other) { + if (depth != other.depth) + return false; + for (int i = 0; i < depth; i++) + if (!locations[i].isSameLocation(other.locations[i])) + return false; + return true; + } + + public static class Location { + public final byte tag; + public final byte index; + + boolean isSameLocation(Location other) { + return tag == other.tag && index == other.index; + } + + public Location(byte tag, byte index) { + this.tag = tag; + this.index = index; + } + } + } + + @Override + public String toString() { + return annotation.toString() + " with Targetnfo: " + + targetInfo.toString() + " on base declaration: " + + baseDeclaration.toString(); + } +} diff --git a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java new file mode 100644 index 00000000000..12abe28b4d5 --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java @@ -0,0 +1,491 @@ +/* + * Copyright (c) 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 sun.reflect.annotation; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.nio.ByteBuffer; +import java.nio.BufferUnderflowException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import sun.misc.JavaLangAccess; +import sun.reflect.ConstantPool; +import static sun.reflect.annotation.TypeAnnotation.*; + +/** + * TypeAnnotationParser implements the logic needed to parse + * TypeAnnotations from an array of bytes. + */ +public class TypeAnnotationParser { + private static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0]; + + /** + * Build an AnnotatedType from the parameters supplied. + * + * This method and {@code buildAnnotatedTypes} are probably + * the entry points you are looking for. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the dclaration this type annotation is on + * @param container the Class this type annotation is on (may be the same as decl) + * @param type the type the AnnotatedType corresponds to + * @param filter the type annotation targets included in this AnnotatedType + */ + public static AnnotatedType buildAnnotatedType(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement decl, + Class container, + Type type, + TypeAnnotationTarget filter) { + TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations, + cp, + decl, + container); + List l = new ArrayList<>(tas.length); + for (TypeAnnotation t : tas) { + TypeAnnotationTargetInfo ti = t.getTargetInfo(); + if (ti.getTarget() == filter) + l.add(t); + } + TypeAnnotation[] typeAnnotations = l.toArray(new TypeAnnotation[0]); + return AnnotatedTypeFactory.buildAnnotatedType(type, + LocationInfo.BASE_LOCATION, + typeAnnotations, + typeAnnotations, + decl); + } + + /** + * Build an array of AnnotatedTypes from the parameters supplied. + * + * This method and {@code buildAnnotatedType} are probably + * the entry points you are looking for. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the declaration this type annotation is on + * @param container the Class this type annotation is on (may be the same as decl) + * @param types the Types the AnnotatedTypes corresponds to + * @param filter the type annotation targets that included in this AnnotatedType + */ + public static AnnotatedType[] buildAnnotatedTypes(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement decl, + Class container, + Type[] types, + TypeAnnotationTarget filter) { + int size = types.length; + AnnotatedType[] result = new AnnotatedType[size]; + Arrays.fill(result, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE); + @SuppressWarnings("rawtypes") + ArrayList[] l = new ArrayList[size]; // array of ArrayList + + TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations, + cp, + decl, + container); + for (TypeAnnotation t : tas) { + TypeAnnotationTargetInfo ti = t.getTargetInfo(); + if (ti.getTarget() == filter) { + int pos = ti.getCount(); + if (l[pos] == null) { + ArrayList tmp = new ArrayList<>(tas.length); + l[pos] = tmp; + } + @SuppressWarnings("unchecked") + ArrayList tmp = l[pos]; + tmp.add(t); + } + } + for (int i = 0; i < size; i++) { + @SuppressWarnings("unchecked") + ArrayList list = l[i]; + if (list != null) { + TypeAnnotation[] typeAnnotations = list.toArray(new TypeAnnotation[0]); + result[i] = AnnotatedTypeFactory.buildAnnotatedType(types[i], + LocationInfo.BASE_LOCATION, + typeAnnotations, + typeAnnotations, + decl); + } + } + return result; + } + + // Class helpers + + /** + * Build an AnnotatedType for the class decl's supertype. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the Class which annotated supertype is being built + */ + public static AnnotatedType buildAnnotatedSuperclass(byte[] rawAnnotations, + ConstantPool cp, + Class decl) { + Type supertype = decl.getGenericSuperclass(); + if (supertype == null) + return AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE; + return buildAnnotatedType(rawAnnotations, + cp, + decl, + decl, + supertype, + TypeAnnotationTarget.CLASS_EXTENDS); + } + + /** + * Build an array of AnnotatedTypes for the class decl's implemented + * interfaces. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the Class whose annotated implemented interfaces is being built + */ + public static AnnotatedType[] buildAnnotatedInterfaces(byte[] rawAnnotations, + ConstantPool cp, + Class decl) { + return buildAnnotatedTypes(rawAnnotations, + cp, + decl, + decl, + decl.getGenericInterfaces(), + TypeAnnotationTarget.CLASS_IMPLEMENTS); + } + + // TypeVariable helpers + + /** + * Parse regular annotations on a TypeVariable declared on genericDecl. + * + * Regular Annotations on TypeVariables are stored in the type + * annotation byte[] in the class file. + * + * @param genericsDecl the declaration declaring the type variable + * @param typeVarIndex the 0-based index of this type variable in the declaration + */ + public static Annotation[] parseTypeVariableAnnotations(D genericDecl, + int typeVarIndex) { + AnnotatedElement decl; + TypeAnnotationTarget predicate; + if (genericDecl instanceof Class) { + decl = (Class)genericDecl; + predicate = TypeAnnotationTarget.CLASS_TYPE_PARAMETER; + } else if (genericDecl instanceof Executable) { + decl = (Executable)genericDecl; + predicate = TypeAnnotationTarget.METHOD_TYPE_PARAMETER; + } else { + throw new AssertionError("Unknown GenericDeclaration " + genericDecl + "\nthis should not happen."); + } + List typeVarAnnos = TypeAnnotation.filter(parseAllTypeAnnotations(decl), + predicate); + List res = new ArrayList<>(typeVarAnnos.size()); + for (TypeAnnotation t : typeVarAnnos) + if (t.getTargetInfo().getCount() == typeVarIndex) + res.add(t.getAnnotation()); + return res.toArray(new Annotation[0]); + } + + /** + * Build an array of AnnotatedTypes for the declaration decl's bounds. + * + * @param bounds the bounds corresponding to the annotated bounds + * @param decl the declaration whose annotated bounds is being built + * @param typeVarIndex the index of this type variable on the decl + */ + public static AnnotatedType[] parseAnnotatedBounds(Type[] bounds, + D decl, + int typeVarIndex) { + return parseAnnotatedBounds(bounds, decl, typeVarIndex, LocationInfo.BASE_LOCATION); + } + //helper for above + static AnnotatedType[] parseAnnotatedBounds(Type[] bounds, + D decl, + int typeVarIndex, + LocationInfo loc) { + List candidates = fetchBounds(decl); + if (bounds != null) { + int startIndex = 0; + AnnotatedType[] res = new AnnotatedType[bounds.length]; + Arrays.fill(res, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE); + + // Adjust bounds index + // + // Figure out if the type annotations for this bound starts with 0 + // or 1. The spec says within a bound the 0:th type annotation will + // always be on an bound of a Class type (not Interface type). So + // if the programmer starts with an Interface type for the first + // (and following) bound(s) the implicit Object bound is considered + // the first (that is 0:th) bound and type annotations start on + // index 1. + if (bounds.length > 0) { + Type b0 = bounds[0]; + if (!(b0 instanceof Class)) { + startIndex = 1; + } else { + Class c = (Class)b0; + if (c.isInterface()) { + startIndex = 1; + } + } + } + + for (int i = 0; i < bounds.length; i++) { + List l = new ArrayList<>(candidates.size()); + for (TypeAnnotation t : candidates) { + TypeAnnotationTargetInfo tInfo = t.getTargetInfo(); + if (tInfo.getSecondaryIndex() == i + startIndex && + tInfo.getCount() == typeVarIndex) { + l.add(t); + } + res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i], + loc, + l.toArray(new TypeAnnotation[0]), + candidates.toArray(new TypeAnnotation[0]), + (AnnotatedElement)decl); + } + } + return res; + } + return new AnnotatedType[0]; + } + private static List fetchBounds(D decl) { + AnnotatedElement boundsDecl; + TypeAnnotationTarget target; + if (decl instanceof Class) { + target = TypeAnnotationTarget.CLASS_PARAMETER_BOUND; + boundsDecl = (Class)decl; + } else { + target = TypeAnnotationTarget.METHOD_PARAMETER_BOUND; + boundsDecl = (Executable)decl; + } + return TypeAnnotation.filter(TypeAnnotationParser.parseAllTypeAnnotations(boundsDecl), target); + } + + /* + * Parse all type annotations on the declaration supplied. This is needed + * when you go from for example an annotated return type on a method that + * is a type variable declared on the class. In this case you need to + * 'jump' to the decl of the class and parse all type annotations there to + * find the ones that are applicable to the type variable. + */ + static TypeAnnotation[] parseAllTypeAnnotations(AnnotatedElement decl) { + Class container; + byte[] rawBytes; + JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess(); + if (decl instanceof Class) { + container = (Class)decl; + rawBytes = javaLangAccess.getRawClassTypeAnnotations(container); + } else if (decl instanceof Executable) { + container = ((Executable)decl).getDeclaringClass(); + rawBytes = javaLangAccess.getRawExecutableTypeAnnotations((Executable)decl); + } else { + // Should not reach here. Assert? + return EMPTY_TYPE_ANNOTATION_ARRAY; + } + return parseTypeAnnotations(rawBytes, javaLangAccess.getConstantPool(container), + decl, container); + } + + /* Parse type annotations encoded as an array of bytes */ + private static TypeAnnotation[] parseTypeAnnotations(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement baseDecl, + Class container) { + if (rawAnnotations == null) + return EMPTY_TYPE_ANNOTATION_ARRAY; + + ByteBuffer buf = ByteBuffer.wrap(rawAnnotations); + int annotationCount = buf.getShort() & 0xFFFF; + List typeAnnotations = new ArrayList<>(annotationCount); + + // Parse each TypeAnnotation + for (int i = 0; i < annotationCount; i++) { + TypeAnnotation ta = parseTypeAnnotation(buf, cp, baseDecl, container); + if (ta != null) + typeAnnotations.add(ta); + } + + return typeAnnotations.toArray(EMPTY_TYPE_ANNOTATION_ARRAY); + } + + + // Helper + static Map, Annotation> mapTypeAnnotations(TypeAnnotation[] typeAnnos) { + Map, Annotation> result = + new LinkedHashMap<>(); + for (TypeAnnotation t : typeAnnos) { + Annotation a = t.getAnnotation(); + Class klass = a.annotationType(); + AnnotationType type = AnnotationType.getInstance(klass); + if (type.retention() == RetentionPolicy.RUNTIME) + if (result.put(klass, a) != null) + throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a); + } + return result; + } + + // Position codes + // Regular type parameter annotations + private static final byte CLASS_TYPE_PARAMETER = 0x00; + private static final byte METHOD_TYPE_PARAMETER = 0x01; + // Type Annotations outside method bodies + private static final byte CLASS_EXTENDS = 0x10; + private static final byte CLASS_TYPE_PARAMETER_BOUND = 0x11; + private static final byte METHOD_TYPE_PARAMETER_BOUND = 0x12; + private static final byte FIELD = 0x13; + private static final byte METHOD_RETURN = 0x14; + private static final byte METHOD_RECEIVER = 0x15; + private static final byte METHOD_FORMAL_PARAMETER = 0x16; + private static final byte THROWS = 0x17; + // Type Annotations inside method bodies + private static final byte LOCAL_VARIABLE = (byte)0x40; + private static final byte RESOURCE_VARIABLE = (byte)0x41; + private static final byte EXCEPTION_PARAMETER = (byte)0x42; + private static final byte CAST = (byte)0x43; + private static final byte INSTANCEOF = (byte)0x44; + private static final byte NEW = (byte)0x45; + private static final byte CONSTRUCTOR_REFERENCE_RECEIVER = (byte)0x46; + private static final byte METHOD_REFERENCE_RECEIVER = (byte)0x47; + private static final byte LAMBDA_FORMAL_PARAMETER = (byte)0x48; + private static final byte METHOD_REFERENCE = (byte)0x49; + private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x50; + + private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf, + ConstantPool cp, + AnnotatedElement baseDecl, + Class container) { + TypeAnnotationTargetInfo ti = parseTargetInfo(buf); + LocationInfo locationInfo = LocationInfo.parseLocationInfo(buf); + Annotation a = AnnotationParser.parseAnnotation(buf, cp, container, false); + if (ti == null) // Inside a method for example + return null; + return new TypeAnnotation(ti, locationInfo, a, baseDecl); + } + + private static TypeAnnotationTargetInfo parseTargetInfo(ByteBuffer buf) { + byte posCode = buf.get(); + switch(posCode) { + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: { + byte index = buf.get(); + TypeAnnotationTargetInfo res; + if (posCode == CLASS_TYPE_PARAMETER) + res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_TYPE_PARAMETER, + index); + else + res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_TYPE_PARAMETER, + index); + return res; + } // unreachable break; + case CLASS_EXTENDS: { + short index = buf.getShort(); + if (index == -1) { + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_EXTENDS); + } else if (index >= 0) { + TypeAnnotationTargetInfo res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_IMPLEMENTS, + index); + return res; + }} break; + case CLASS_TYPE_PARAMETER_BOUND: + return parse2ByteTarget(TypeAnnotationTarget.CLASS_PARAMETER_BOUND, buf); + case METHOD_TYPE_PARAMETER_BOUND: + return parse2ByteTarget(TypeAnnotationTarget.METHOD_PARAMETER_BOUND, buf); + case FIELD: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD_TYPE); + case METHOD_RETURN: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN_TYPE); + case METHOD_RECEIVER: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER_TYPE); + case METHOD_FORMAL_PARAMETER: { + // Todo + byte index = buf.get(); + } break; + case THROWS: + return parseShortTarget(TypeAnnotationTarget.THROWS, buf); + + /* + * The ones below are inside method bodies, we don't care about them for core reflection + * other than adjusting for them in the byte stream. + */ + case LOCAL_VARIABLE: + case RESOURCE_VARIABLE: + short length = buf.getShort(); + for (int i = 0; i < length; ++i) { + short offset = buf.getShort(); + short varLength = buf.getShort(); + short index = buf.getShort(); + } + break; + case EXCEPTION_PARAMETER: { + byte index = buf.get(); + } break; + case CAST: + case INSTANCEOF: + case NEW: { + short offset = buf.getShort(); + } break; + case CONSTRUCTOR_REFERENCE_RECEIVER: + case METHOD_REFERENCE_RECEIVER: { + short offset = buf.getShort(); + byte index = buf.get(); + } break; + case LAMBDA_FORMAL_PARAMETER: { + byte index = buf.get(); + } break; + case METHOD_REFERENCE: + // This one isn't in the spec yet + break; + case METHOD_REFERENCE_TYPE_ARGUMENT: { + short offset = buf.getShort(); + byte index = buf.get(); + } break; + + default: + // will throw error below + break; + } + throw new AnnotationFormatError("Could not parse bytes for type annotations"); + } + + private static TypeAnnotationTargetInfo parseShortTarget(TypeAnnotationTarget target, ByteBuffer buf) { + short index = buf.getShort(); + return new TypeAnnotationTargetInfo(target, index); + } + private static TypeAnnotationTargetInfo parse2ByteTarget(TypeAnnotationTarget target, ByteBuffer buf) { + byte count = buf.get(); + byte secondaryIndex = buf.get(); + return new TypeAnnotationTargetInfo(target, + count, + secondaryIndex); + } +} diff --git a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java index 021b84891f1..528658d0d16 100644 --- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,18 @@ package sun.reflect.generics.reflectiveObjects; -import java.lang.annotation.Annotation; +import java.lang.annotation.*; +import java.lang.reflect.AnnotatedType; import java.lang.reflect.Array; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Objects; - +import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.annotation.AnnotationType; import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.tree.FieldTypeSignature; import sun.reflect.generics.visitor.Reifier; @@ -182,45 +187,70 @@ public class TypeVariableImpl return genericDeclaration.hashCode() ^ name.hashCode(); } - // Currently vacuous implementations of AnnotatedElement methods. - public boolean isAnnotationPresent(Class annotationClass) { - Objects.requireNonNull(annotationClass); - return false; - } - + // Implementations of AnnotatedElement methods. + @SuppressWarnings("unchecked") public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - return null; + // T is an Annotation type, the return value of get will be an annotation + return (T)mapAnnotations(getAnnotations()).get(annotationClass); } public T getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - return null; + return getAnnotation(annotationClass); } - @SuppressWarnings("unchecked") public T[] getAnnotations(Class annotationClass) { Objects.requireNonNull(annotationClass); - // safe because annotationClass is the class for T - return (T[])Array.newInstance(annotationClass, 0); + return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass); } - @SuppressWarnings("unchecked") public T[] getDeclaredAnnotations(Class annotationClass) { Objects.requireNonNull(annotationClass); - // safe because annotationClass is the class for T - return (T[])Array.newInstance(annotationClass, 0); + return getAnnotations(annotationClass); } public Annotation[] getAnnotations() { - // Since zero-length, don't need defensive clone - return EMPTY_ANNOTATION_ARRAY; + int myIndex = typeVarIndex(); + if (myIndex < 0) + throw new AssertionError("Index must be non-negative."); + return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex); } public Annotation[] getDeclaredAnnotations() { - // Since zero-length, don't need defensive clone - return EMPTY_ANNOTATION_ARRAY; + return getAnnotations(); + } + + public AnnotatedType[] getAnnotatedBounds() { + return TypeAnnotationParser.parseAnnotatedBounds(getBounds(), + getGenericDeclaration(), + typeVarIndex()); } private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; + + // Helpers for annotation methods + private int typeVarIndex() { + TypeVariable[] tVars = getGenericDeclaration().getTypeParameters(); + int i = -1; + for (TypeVariable v : tVars) { + i++; + if (equals(v)) + return i; + } + return -1; + } + + private static Map, Annotation> mapAnnotations(Annotation[] annos) { + Map, Annotation> result = + new LinkedHashMap<>(); + for (Annotation a : annos) { + Class klass = a.annotationType(); + AnnotationType type = AnnotationType.getInstance(klass); + if (type.retention() == RetentionPolicy.RUNTIME) + if (result.put(klass, a) != null) + throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a); + } + return result; + } } diff --git a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index eefdbff811f..d40e033d9f0 100644 --- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -1116,7 +1116,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { if (privateKeyCount > 0 || secretKeyCount > 0) { if (debug != null) { - debug.println("Storing " + privateKeyCount + + debug.println("Storing " + (privateKeyCount + secretKeyCount) + " protected key(s) in a PKCS#7 data content-type"); } @@ -2122,6 +2122,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { SecretKeyEntry kEntry = new SecretKeyEntry(); kEntry.protectedSecretKey = secretValue.getOctetString(); bagItem = kEntry; + secretKeyCount++; } else { if (debug != null) { @@ -2220,6 +2221,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi { if (bagItem instanceof PrivateKeyEntry) { keyList.add((PrivateKeyEntry) entry); } + if (entry.attributes == null) { + entry.attributes = new HashSet<>(); + } + entry.attributes.addAll(attributes); if (alias == null) { alias = getUnfriendlyName(); } diff --git a/jdk/src/share/javavm/export/jvm.h b/jdk/src/share/javavm/export/jvm.h index 28885cfb14d..56a8abb03cc 100644 --- a/jdk/src/share/javavm/export/jvm.h +++ b/jdk/src/share/javavm/export/jvm.h @@ -465,6 +465,12 @@ JVM_GetClassSignature(JNIEnv *env, jclass cls); JNIEXPORT jbyteArray JNICALL JVM_GetClassAnnotations(JNIEnv *env, jclass cls); +/* Type use annotations support (JDK 1.8) */ + +JNIEXPORT jbyteArray JNICALL +JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls); + + /* * New (JDK 1.4) reflection implementation */ diff --git a/jdk/src/share/native/java/lang/Class.c b/jdk/src/share/native/java/lang/Class.c index 3e595e726af..20d03060101 100644 --- a/jdk/src/share/native/java/lang/Class.c +++ b/jdk/src/share/native/java/lang/Class.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -75,7 +75,8 @@ static JNINativeMethod methods[] = { {"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations}, {"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool}, {"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus}, - {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo} + {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo}, + {"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations}, }; #undef OBJ diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.c b/jdk/src/share/native/sun/awt/image/awt_parseImage.c index 264a02f1642..d6f6d60d356 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c @@ -489,6 +489,71 @@ void awt_freeParsedImage(BufImageS_t *imageP, int freeImageP) { } } +static void +awt_getBIColorOrder(int type, int *colorOrder) { + switch(type) { + case java_awt_image_BufferedImage_TYPE_INT_ARGB: + case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; + colorOrder[3] = 3; +#else + colorOrder[0] = 1; + colorOrder[1] = 2; + colorOrder[2] = 3; + colorOrder[3] = 0; +#endif + break; + case java_awt_image_BufferedImage_TYPE_INT_BGR: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 0; + colorOrder[1] = 1; + colorOrder[2] = 2; +#else + colorOrder[0] = 3; + colorOrder[1] = 2; + colorOrder[2] = 1; +#endif + break; + case java_awt_image_BufferedImage_TYPE_INT_RGB: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; +#else + colorOrder[0] = 1; + colorOrder[1] = 2; + colorOrder[2] = 3; +#endif + break; + case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: + case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: + colorOrder[0] = 3; + colorOrder[1] = 2; + colorOrder[2] = 1; + colorOrder[3] = 0; + break; + case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; + break; + case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: + case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: + colorOrder[0] = 0; + colorOrder[1] = 1; + colorOrder[2] = 2; + break; + case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: + case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: + case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: + case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: + colorOrder[0] = 0; + break; + } +} static int setHints(JNIEnv *env, BufImageS_t *imageP) { diff --git a/jdk/src/solaris/native/java/net/linux_close.c b/jdk/src/solaris/native/java/net/linux_close.c index 5665e85e09c..51f9cb2ee70 100644 --- a/jdk/src/solaris/native/java/net/linux_close.c +++ b/jdk/src/solaris/native/java/net/linux_close.c @@ -191,17 +191,6 @@ static int closefd(int fd1, int fd2) { pthread_mutex_lock(&(fdEntry->lock)); { - /* - * Send a wakeup signal to all threads blocked on this - * file descriptor. - */ - threadEntry_t *curr = fdEntry->threads; - while (curr != NULL) { - curr->intr = 1; - pthread_kill( curr->thr, sigWakeup ); - curr = curr->next; - } - /* * And close/dup the file descriptor * (restart if interrupted by signal) @@ -214,6 +203,16 @@ static int closefd(int fd1, int fd2) { } } while (rv == -1 && errno == EINTR); + /* + * Send a wakeup signal to all threads blocked on this + * file descriptor. + */ + threadEntry_t *curr = fdEntry->threads; + while (curr != NULL) { + curr->intr = 1; + pthread_kill( curr->thr, sigWakeup ); + curr = curr->next; + } } /* diff --git a/jdk/src/solaris/native/sun/awt/awt_Mlib.c b/jdk/src/solaris/native/sun/awt/awt_Mlib.c index fb00d4d9f12..0b7c291c811 100644 --- a/jdk/src/solaris/native/sun/awt/awt_Mlib.c +++ b/jdk/src/solaris/native/sun/awt/awt_Mlib.c @@ -145,52 +145,6 @@ mlib_stop_timer awt_setMlibStopTimer() { return stop_timer; } -void awt_getBIColorOrder(int type, int *colorOrder) { - switch(type) { - case java_awt_image_BufferedImage_TYPE_INT_ARGB: - case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: - colorOrder[0] = 1; - colorOrder[1] = 2; - colorOrder[2] = 3; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_INT_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: - colorOrder[0] = 3; - colorOrder[1] = 2; - colorOrder[2] = 1; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_INT_RGB: - colorOrder[0] = 1; - colorOrder[1] = 2; - colorOrder[2] = 3; - break; - case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: - case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: - case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: - case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: - case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: - colorOrder[0] = 0; - break; - } -} - /*************************************************************************** * Static Functions * ***************************************************************************/ diff --git a/jdk/src/solaris/native/sun/awt/awt_Mlib.h b/jdk/src/solaris/native/sun/awt/awt_Mlib.h index 03d65868994..cbaf38d1de6 100644 --- a/jdk/src/solaris/native/sun/awt/awt_Mlib.h +++ b/jdk/src/solaris/native/sun/awt/awt_Mlib.h @@ -33,6 +33,5 @@ typedef void (*mlib_stop_timer)(int, int); mlib_status awt_getImagingLib(JNIEnv *, mlibFnS_t *, mlibSysFnS_t *); mlib_start_timer awt_setMlibStartTimer(); mlib_stop_timer awt_setMlibStopTimer(); -void awt_getBIColorOrder(int type, int *colorOrder); #endif /* _AWT_MLIB_H */ diff --git a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c index 5b8aeb4be20..cee9bb75bfd 100644 --- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c +++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c @@ -135,11 +135,11 @@ jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps) useMitShmPixmaps = JNI_FALSE; } } - - return JNI_TRUE; #endif /* MITSHM */ #endif /* !HEADLESS */ + + return JNI_TRUE; } @@ -468,8 +468,8 @@ jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width return JNI_FALSE; } - return JNI_TRUE; #endif /* !HEADLESS */ + return JNI_TRUE; } diff --git a/jdk/src/windows/bin/cmdtoargs.c b/jdk/src/windows/bin/cmdtoargs.c index 4e92d18708c..669f3683bfe 100644 --- a/jdk/src/windows/bin/cmdtoargs.c +++ b/jdk/src/windows/bin/cmdtoargs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -104,6 +104,11 @@ static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) { case ' ': case '\t': + if (prev == '\\') { + for (i = 0 ; i < slashes; i++) { + *dest++ = prev; + } + } if (quotes % 2 == 1) { *dest++ = ch; } else { @@ -591,6 +596,12 @@ int main(int argc, char* argv[]) { // v->disable(); vectors[i++] = v; + v= new Vector(argv[0], "a b\\\\ d"); + v->add("a", FALSE); + v->add("b\\\\", FALSE); + v->add("d", FALSE); + vectors[i++] = v; + dotest(vectors); printf("All tests pass [%d]\n", i); doexit(0); diff --git a/jdk/src/windows/native/sun/windows/awt_Mlib.cpp b/jdk/src/windows/native/sun/windows/awt_Mlib.cpp index 022ebd0419a..308b2823e4c 100644 --- a/jdk/src/windows/native/sun/windows/awt_Mlib.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Mlib.cpp @@ -105,50 +105,4 @@ extern "C" mlib_stop_timer awt_setMlibStopTimer() { return NULL; } - - void awt_getBIColorOrder(int type, int *colorOrder) { - switch(type) { - case java_awt_image_BufferedImage_TYPE_INT_ARGB: - case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - colorOrder[3] = 3; - break; - case java_awt_image_BufferedImage_TYPE_INT_BGR: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_INT_RGB: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: - colorOrder[0] = 3; - colorOrder[1] = 2; - colorOrder[2] = 1; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: - case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: - case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: - case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: - case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: - colorOrder[0] = 0; - break; - } - } } diff --git a/jdk/src/windows/native/sun/windows/awt_Mlib.h b/jdk/src/windows/native/sun/windows/awt_Mlib.h index f9b63d900bb..9ebee32a932 100644 --- a/jdk/src/windows/native/sun/windows/awt_Mlib.h +++ b/jdk/src/windows/native/sun/windows/awt_Mlib.h @@ -38,7 +38,6 @@ JNIEXPORT mlib_status awt_getImagingLib(JNIEnv *env, mlibFnS_t *sMlibFns, mlibSysFnS_t *sMlibSysFns); JNIEXPORT mlib_start_timer awt_setMlibStartTimer(); JNIEXPORT mlib_stop_timer awt_setMlibStopTimer(); -JNIEXPORT void awt_getBIColorOrder(int type, int *colorOrder); #ifdef __cplusplus }; /* end of extern "C" */ diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5e181ac7e03..1870b0b9219 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -321,12 +321,12 @@ sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all tools/pack200/CommandLineTests.java generic-all tools/pack200/Pack200Test.java generic-all -# 8001163 -tools/pack200/AttributeTests.java generic-all - # 7150569 tools/launcher/UnicodeTest.java macosx-all +# 8007410 +tools/launcher/FXLauncherTest.java linux-all + ############################################################################ # jdk_jdi diff --git a/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java b/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java new file mode 100644 index 00000000000..62de1683827 --- /dev/null +++ b/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8004801 + * @summary Test verifies that byte lookup table with single lookup + * affects only color components in buffered images with + * integer data type, and that this operation does not distort + * colors in the destination image. + * @run main IntImageReverseTest + */ + +import java.awt.image.BufferedImage; +import java.awt.image.ByteLookupTable; +import java.awt.image.LookupOp; +import java.awt.image.LookupTable; + +public class IntImageReverseTest { + + public static void main(String[] args) { + LookupTable tbl = createReverseTable(); + LookupOp op = new LookupOp(tbl, null); + + for (ImageType t : ImageType.values()) { + System.out.print(t); + + BufferedImage src = createSourceImage(t); + + BufferedImage dst = op.filter(src, null); + + int rgb = dst.getRGB(0, 0); + + System.out.printf(" Result: 0x%X ", rgb); + + if (rgb != argbReverse) { + throw new RuntimeException("Test failed."); + } + System.out.println("Passed."); + } + } + + /** + * Reverse image color components, leave alpha unchanged. + */ + private static LookupTable createReverseTable() { + byte[] data = new byte[256]; + + for (int i = 0; i < 256; i++) { + data[i] = (byte) (255 - i); + } + + + return new ByteLookupTable(0, data); + } + + private static BufferedImage createSourceImage(ImageType type) { + BufferedImage img = new BufferedImage(1, 1, type.bi_type); + + img.setRGB(0, 0, argbTest); + + return img; + } + private static final int argbTest = 0xFFDDAA77; + private static final int argbReverse = 0xFF225588; + + private static enum ImageType { + + INT_ARGB(BufferedImage.TYPE_INT_ARGB), + INT_ARGB_PRE(BufferedImage.TYPE_INT_ARGB_PRE), + INT_RGB(BufferedImage.TYPE_INT_BGR), + INT_BGR(BufferedImage.TYPE_INT_BGR); + + private ImageType(int bi_type) { + this.bi_type = bi_type; + } + public final int bi_type; + } +} diff --git a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java new file mode 100644 index 00000000000..b3aad9726a9 --- /dev/null +++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java @@ -0,0 +1,428 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8004698 + * @summary Unit test for type annotations + */ + +import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.io.Serializable; + +public class TypeAnnotationReflection { + public static void main(String[] args) throws Exception { + testSuper(); + testInterfaces(); + testReturnType(); + testNested(); + testArray(); + testRunException(); + testClassTypeVarBounds(); + testMethodTypeVarBounds(); + testFields(); + testClassTypeVar(); + testMethodTypeVar(); + testParameterizedType(); + testNestedParameterizedType(); + testWildcardType(); + } + + private static void check(boolean b) { + if (!b) + throw new RuntimeException(); + } + + private static void testSuper() throws Exception { + check(Object.class.getAnnotatedSuperclass().getAnnotations().length == 0); + check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0); + + AnnotatedType a; + a = TestClassArray.class.getAnnotatedSuperclass(); + Annotation[] annos = a.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("extends")); + check(((TypeAnno2)annos[1]).value().equals("extends2")); + } + + private static void testInterfaces() throws Exception { + AnnotatedType[] as; + as = TestClassArray.class.getAnnotatedInterfaces(); + check(as.length == 3); + check(as[1].getAnnotations().length == 0); + + Annotation[] annos; + annos = as[0].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("implements serializable")); + check(((TypeAnno2)annos[1]).value().equals("implements2 serializable")); + + annos = as[2].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("implements cloneable")); + check(((TypeAnno2)annos[1]).value().equals("implements2 cloneable")); + } + + private static void testReturnType() throws Exception { + Method m = TestClassArray.class.getDeclaredMethod("foo", (Class[])null); + Annotation[] annos = m.getAnnotatedReturnType().getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return1")); + } + + private static void testNested() throws Exception { + Method m = TestClassNested.class.getDeclaredMethod("foo", (Class[])null); + Annotation[] annos = m.getAnnotatedReturnType().getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("array")); + + AnnotatedType t = m.getAnnotatedReturnType(); + t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Inner")); + } + + private static void testArray() throws Exception { + Method m = TestClassArray.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedArrayType t = (AnnotatedArrayType) m.getAnnotatedReturnType(); + Annotation[] annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return1")); + + t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 0); + + t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return3")); + + AnnotatedType tt = t.getAnnotatedGenericComponentType(); + check(!(tt instanceof AnnotatedArrayType)); + annos = tt.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return4")); + } + + private static void testRunException() throws Exception { + Method m = TestClassException.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType[] ts = m.getAnnotatedExceptionTypes(); + check(ts.length == 3); + + AnnotatedType t; + Annotation[] annos; + t = ts[0]; + annos = t.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("RE")); + check(((TypeAnno2)annos[1]).value().equals("RE2")); + + t = ts[1]; + annos = t.getAnnotations(); + check(annos.length == 0); + + t = ts[2]; + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("AIOOBE")); + } + + private static void testClassTypeVarBounds() throws Exception { + Method m = TestClassTypeVarAndField.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + Annotation[] annos = ret.getAnnotations(); + check(annos.length == 2); + + AnnotatedType[] annotatedBounds = ((AnnotatedTypeVariable)ret).getAnnotatedBounds(); + check(annotatedBounds.length == 2); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object1")); + + annos = annotatedBounds[1].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("Runnable1")); + check(((TypeAnno2)annos[1]).value().equals("Runnable2")); + } + + private static void testMethodTypeVarBounds() throws Exception { + Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class[])null); + AnnotatedType ret2 = m2.getAnnotatedReturnType(); + AnnotatedType[] annotatedBounds2 = ((AnnotatedTypeVariable)ret2).getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + Annotation[] annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("M Runnable")); + } + + private static void testFields() throws Exception { + Field f1 = TestClassTypeVarAndField.class.getDeclaredField("field1"); + AnnotatedType at; + Annotation[] annos; + + at = f1.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("T1 field")); + check(((TypeAnno2)annos[1]).value().equals("T2 field")); + + Field f2 = TestClassTypeVarAndField.class.getDeclaredField("field2"); + at = f2.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 0); + + Field f3 = TestClassTypeVarAndField.class.getDeclaredField("field3"); + at = f3.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object field")); + } + + private static void testClassTypeVar() throws Exception { + TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters(); + Annotation[] annos; + check(typeVars.length == 2); + + // First TypeVar + AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds(); + check(annotatedBounds.length == 2); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object1")); + + annos = annotatedBounds[1].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("Runnable1")); + check(((TypeAnno2)annos[1]).value().equals("Runnable2")); + + // second TypeVar regular anno + Annotation[] regularAnnos = typeVars[1].getAnnotations(); + check(regularAnnos.length == 1); + check(typeVars[1].getAnnotation(TypeAnno.class).value().equals("EE")); + + // second TypeVar + annotatedBounds = typeVars[1].getAnnotatedBounds(); + check(annotatedBounds.length == 1); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno2)annos[0]).value().equals("EEBound")); + } + + private static void testMethodTypeVar() throws Exception { + Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class[])null); + TypeVariable[] t = m2.getTypeParameters(); + check(t.length == 1); + Annotation[] annos = t[0].getAnnotations(); + check(annos.length == 0); + + AnnotatedType[] annotatedBounds2 = t[0].getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("M Runnable")); + + // Second method + m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class[])null); + t = m2.getTypeParameters(); + check(t.length == 1); + annos = t[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("K")); + + annotatedBounds2 = t[0].getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 0); + } + + private static void testParameterizedType() { + // Base + AnnotatedType[] as; + as = TestParameterizedType.class.getAnnotatedInterfaces(); + check(as.length == 1); + check(as[0].getAnnotations().length == 1); + check(as[0].getAnnotation(TypeAnno.class).value().equals("M")); + + Annotation[] annos; + as = ((AnnotatedParameterizedType)as[0]).getAnnotatedActualTypeArguments(); + check(as.length == 2); + annos = as[0].getAnnotations(); + check(annos.length == 1); + check(as[0].getAnnotation(TypeAnno.class).value().equals("S")); + check(as[0].getAnnotation(TypeAnno2.class) == null); + + annos = as[1].getAnnotations(); + check(annos.length == 2); + check(((TypeAnno)annos[0]).value().equals("I")); + check(as[1].getAnnotation(TypeAnno2.class).value().equals("I2")); + } + + private static void testNestedParameterizedType() throws Exception { + Method m = TestParameterizedType.class.getDeclaredMethod("foo2", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + Annotation[] annos; + annos = ret.getAnnotations(); + check(annos.length == 1); + check(((TypeAnno)annos[0]).value().equals("I")); + + AnnotatedType[] args = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments(); + check(args.length == 1); + annos = args[0].getAnnotations(); + check(annos.length == 2); + check(((TypeAnno)annos[0]).value().equals("I1")); + check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2")); + } + + private static void testWildcardType() throws Exception { + Method m = TestWildcardType.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + AnnotatedType[] t; + t = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments(); + check(t.length == 1); + ret = t[0]; + + Field f = TestWildcardType.class.getDeclaredField("f1"); + AnnotatedWildcardType w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f + .getAnnotatedType()).getAnnotatedActualTypeArguments()[0]; + t = w.getAnnotatedLowerBounds(); + check(t.length == 0); + t = w.getAnnotatedUpperBounds(); + check(t.length == 1); + Annotation[] annos; + annos = t[0].getAnnotations(); + check(annos.length == 1); + check(((TypeAnno)annos[0]).value().equals("2")); + + f = TestWildcardType.class.getDeclaredField("f2"); + w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f + .getAnnotatedType()).getAnnotatedActualTypeArguments()[0]; + t = w.getAnnotatedUpperBounds(); + check(t.length == 0); + t = w.getAnnotatedLowerBounds(); + check(t.length == 1); + } +} + +abstract class TestWildcardType { + public List foo() { return null;} + public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1; + public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2; +} + +abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> { + public ParameterizedOuter.ParameterizedInner foo() {return null;} + public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>. + @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() { + return null; + } +} + +class ParameterizedOuter { + class ParameterizedInner {} +} + +abstract class TestClassArray extends @TypeAnno("extends") @TypeAnno2("extends2") Object + implements @TypeAnno("implements serializable") @TypeAnno2("implements2 serializable") Serializable, + Readable, + @TypeAnno("implements cloneable") @TypeAnno2("implements2 cloneable") Cloneable { + public @TypeAnno("return4") Object @TypeAnno("return1") [][] @TypeAnno("return3")[] foo() { return null; } +} + +abstract class TestClassNested { + public @TypeAnno("Outer") Outer.@TypeAnno("Inner")Inner @TypeAnno("array")[] foo() { return null; } +} + +class Outer { + class Inner { + } +} + +abstract class TestClassException { + public Object foo() throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException, + NullPointerException, + @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException { + return null; + } +} + +abstract class TestClassTypeVarAndField { + @TypeAnno("T1 field") @TypeAnno2("T2 field") T field1; + T field2; + @TypeAnno("Object field") Object field3; + + public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; } + public M foo2() {return null;} + public <@TypeAnno("K") K extends Cloneable> K foo3() {return null;} +} + +@Target(ElementType.TYPE_USE) +@Retention(RetentionPolicy.RUNTIME) +@interface TypeAnno { + String value(); +} + +@Target(ElementType.TYPE_USE) +@Retention(RetentionPolicy.RUNTIME) +@interface TypeAnno2 { + String value(); +} diff --git a/jdk/test/java/lang/annotation/TypeParamAnnotation.java b/jdk/test/java/lang/annotation/TypeParamAnnotation.java new file mode 100644 index 00000000000..50457ec46b1 --- /dev/null +++ b/jdk/test/java/lang/annotation/TypeParamAnnotation.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8004698 + * @summary Unit test for annotations on TypeVariables + */ + +import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.io.Serializable; + +public class TypeParamAnnotation { + public static void main(String[] args) throws Exception { + testOnClass(); + testOnMethod(); + testGetAnno(); + testGetAnnos(); + } + + private static void check(boolean b) { + if (!b) + throw new RuntimeException(); + } + + private static void testOnClass() { + TypeVariable[] ts = TypeParam.class.getTypeParameters(); + check(ts.length == 3); + + Annotation[] as; + + as = ts[0].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("t")); + check(((ParamAnno2)as[1]).value() == 1); + + as = ts[1].getAnnotations(); + check(as.length == 0); + + as = ts[2].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("v")); + check(((ParamAnno2)as[1]).value() == 2); + } + private static void testOnMethod() throws Exception { + TypeVariable[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters(); + check(ts.length == 3); + + Annotation[] as; + + as = ts[0].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("x")); + check(((ParamAnno2)as[1]).value() == 3); + + as = ts[1].getAnnotations(); + check(as.length == 0); + + as = ts[2].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("z")); + check(((ParamAnno2)as[1]).value() == 4); + } + + private static void testGetAnno() { + TypeVariable[] ts = TypeParam.class.getTypeParameters(); + ParamAnno a; + a = ts[0].getAnnotation(ParamAnno.class); + check(a.value().equals("t")); + } + private static void testGetAnnos() throws Exception { + TypeVariable[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters(); + ParamAnno2[] as; + as = ts[0].getAnnotations(ParamAnno2.class); + check(as.length == 1); + check(as[0].value() == 3); + } +} + +class TypeParam <@ParamAnno("t") @ParamAnno2(1) T, + U, + @ParamAnno("v") @ParamAnno2(2) V extends Runnable> { + public <@ParamAnno("x") @ParamAnno2(3) X, + Y, + @ParamAnno("z") @ParamAnno2(4) Z extends Cloneable> void foo() {} +} + +@Target(ElementType.TYPE_PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@interface ParamAnno { + String value(); +} + +@Target(ElementType.TYPE_PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@interface ParamAnno2 { + int value(); +} diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java index 0d9cb59d1c4..10e3d746261 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 7154390 + * @bug 7154390 8005712 * @summary Unit test for repeated annotation reflection * * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java @@ -58,7 +58,7 @@ public class RepeatedUnitTest { checkMultiplier(Me1.class.getField("foo"), 1); // METHOD - checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100); + checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class[])null), 100); // INNER CLASS checkMultiplier(Me1.MiniMee.class, 1000); @@ -84,8 +84,7 @@ public class RepeatedUnitTest { static void packageRepeated(AnnotatedElement e) { Containee c = e.getAnnotation(Containee.class); - check(c.value() == 1); - + check(c == null); check(2 == countAnnotation(e, Containee.class)); c = e.getAnnotations(Containee.class)[0]; @@ -93,7 +92,7 @@ public class RepeatedUnitTest { c = e.getAnnotations(Containee.class)[1]; check(c.value() == 2); - check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); + check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); } static void packageContainer(AnnotatedElement e) { @@ -161,14 +160,26 @@ public class RepeatedUnitTest { } static void checkMultiplier(AnnotatedElement e, int m) { + // Basic sanity of non-repeating getAnnotation(Class) check(e.getAnnotation(NonRepeated.class).value() == 5 * m); + // Check count of annotations returned from getAnnotations(Class) check(4 == countAnnotation(e, Containee.class)); check(1 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, NonRepeated.class)); + // Check contents of array returned from getAnnotations(Class) check(e.getAnnotations(Containee.class)[2].value() == 3 * m); check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m); + + // Check getAnnotation(Class) + check(e.getAnnotation(Containee.class) == null); + check(e.getAnnotation(Container.class) != null); + + // Check count of annotations returned from getAnnotations() + check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); + check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class)); + check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class)); } static void check(Boolean b) { diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java index c977b2e5c2d..cca790696d6 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -26,7 +26,6 @@ package subpackage; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Container.class) @Repeatable(Container.class) public @interface Containee { int value(); diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java index e8e2f05ab55..f4d370b7add 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -26,7 +26,6 @@ package subpackage; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainerFor(Containee.class) public @interface Container { Containee[] value(); } diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java index 080d12ce3f5..37f44932a86 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,7 +27,6 @@ import java.lang.annotation.*; @Inherited @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(InheritedContainer.class) @Repeatable(InheritedContainer.class) public @interface InheritedContainee { int value(); diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java index a66af4f6ed8..bff3082520e 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,7 +27,6 @@ import java.lang.annotation.*; @Inherited @Retention(RetentionPolicy.RUNTIME) -@ContainerFor(InheritedContainee.class) public @interface InheritedContainer { InheritedContainee[] value(); } diff --git a/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java b/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java index 39be21471aa..50254fd9d6b 100644 --- a/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java +++ b/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java @@ -23,163 +23,152 @@ /* * @test + * @bug 8004729 * @summary javac should generate method parameters correctly. */ import java.lang.*; import java.lang.reflect.*; +import java.lang.annotation.*; import java.util.List; +import java.util.Objects; + +import static java.lang.annotation.ElementType.*; public class WithoutParameters { + int errors = 0; - private static final Class[] qux_types = { - int.class, - Foo.class, - List.class, - List.class, - List.class, - String[].class - }; + private WithoutParameters() {} public static void main(String argv[]) throws Exception { - int error = 0; - Method[] methods = Foo.class.getMethods(); - for(Method m : methods) { - System.err.println("Inspecting method " + m); - Parameter[] parameters = m.getParameters(); - if(parameters == null) - throw new Exception("getParameters should never be null"); - for(int i = 0; i < parameters.length; i++) { - Parameter p = parameters[i]; - if(!p.getDeclaringExecutable().equals(m)) { - System.err.println(p + ".getDeclaringExecutable != " + m); - error++; - } - if(null == p.getType()) { - System.err.println(p + ".getType() == null"); - error++; - } - if(null == p.getParameterizedType()) { - System.err.println(p + ".getParameterizedType == null"); - error++; - } - } - if(m.getName().equals("qux")) { - if(6 != parameters.length) { - System.err.println("Wrong number of parameters for qux"); - error++; - } - for(int i = 0; i < parameters.length; i++) { - Parameter p = parameters[i]; - // The getType family work with or without - // parameter attributes compiled in. - if(!parameters[i].getType().equals(qux_types[i])) { - System.err.println("Wrong parameter type for " + parameters[0] + ": expected " + qux_types[i] + ", but got " + parameters[i].getType()); - error++; - } - } - if(!parameters[0].getParameterizedType().equals(int.class)) { - System.err.println("getParameterizedType for quux is wrong"); - error++; - } - if(!parameters[1].getParameterizedType().equals(Foo.class)) { - System.err.println("getParameterizedType for quux is wrong"); - error++; - } - if(!(parameters[2].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[2].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) { - System.err.println("Type parameter for l is wrong"); - error++; - } - } - if(!(parameters[3].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l2 is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[3].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l2 is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l2 is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0].equals(Foo.class))) { - System.err.println("Type parameter for l2 is wrong"); - error++; - } - } - if(!(parameters[4].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l3 is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[4].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l3 is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l3 is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) { - System.err.println("Type parameter for l3 is wrong"); - error++; - } else { - WildcardType wt = (WildcardType) - pt.getActualTypeArguments()[0]; - if(!wt.getUpperBounds()[0].equals(Foo.class)) { - System.err.println("Upper bounds on type parameter fol l3 is wrong"); - error++; - } - } - } - if(!parameters[5].isVarArgs()) { - System.err.println("isVarArg for rest is wrong"); - error++; - } - if(!(parameters[5].getParameterizedType().equals(String[].class))) { - System.err.println("getParameterizedType for rest is wrong"); - error++; - } + WithoutParameters wp = new WithoutParameters(); + wp.runTests(Foo.class.getMethods()); + wp.runTests(Foo.Inner.class.getConstructors()); + wp.checkForErrors(); + } + void runTests(Method[] methods) throws Exception { + for(Method m : methods) {runTest(m);} + } + + void runTests(Constructor[] constructors) throws Exception { + for(Constructor c : constructors) {runTest(c);} + } + + void runTest(Executable e) throws Exception { + System.err.println("Inspecting executable " + e); + Parameter[] parameters = e.getParameters(); + Objects.requireNonNull(parameters, "getParameters should never be null"); + + ExpectedParameterInfo epi = e.getAnnotation(ExpectedParameterInfo.class); + if (epi != null) { + abortIfTrue(epi.parameterCount() != e.getParameterCount(), "Bad parameter count for "+ e); + abortIfTrue(epi.isVarArgs() != e.isVarArgs(),"Bad varargs value for "+ e); + } + abortIfTrue(e.getParameterCount() != parameters.length, "Mismatched of parameter counts."); + + for(int i = 0; i < parameters.length; i++) { + Parameter p = parameters[i]; + errorIfTrue(!p.getDeclaringExecutable().equals(e), p + ".getDeclaringExecutable != " + e); + Objects.requireNonNull(p.getType(), "getType() should not be null"); + Objects.requireNonNull(p.getParameterizedType(), "getParameterizedType() should not be null"); + + if (epi != null) { + Class expectedParameterType = epi.parameterTypes()[i]; + errorIfTrue(!p.getType().equals(expectedParameterType), + "Wrong parameter type for " + p + ": expected " + expectedParameterType + + ", but got " + p.getType()); + + ParameterizedInfo[] expectedParameterizedTypes = epi.parameterizedTypes(); + if (expectedParameterizedTypes.length > 0) { + Type parameterizedType = p.getParameterizedType(); + Class expectedParameterziedTypeType = expectedParameterizedTypes[i].value(); + errorIfTrue(!expectedParameterziedTypeType.isAssignableFrom(parameterizedType.getClass()), + "Wrong class of parameteried type of " + p + ": expected " + expectedParameterziedTypeType + + ", but got " + parameterizedType.getClass()); + + if (expectedParameterziedTypeType.equals(Class.class)) { + errorIfTrue(!parameterizedType.equals(expectedParameterType), + "Wrong parameteried type for " + p + ": expected " + expectedParameterType + + ", but got " + parameterizedType); + } else { + if (expectedParameterziedTypeType.equals(ParameterizedType.class)) { + ParameterizedType ptype = (ParameterizedType)parameterizedType; + errorIfTrue(!ptype.getRawType().equals(expectedParameterType), + "Wrong raw type for " + p + ": expected " + expectedParameterType + + ", but got " + ptype.getRawType()); + } + + // Check string representation + String expectedStringOfType = epi.parameterizedTypes()[i].string(); + errorIfTrue(!expectedStringOfType.equals(parameterizedType.toString()), + "Bad type string" + p + ": expected " + expectedStringOfType + + ", but got " + parameterizedType.toString()); + } + } } } - if(0 != error) - throw new Exception("Failed " + error + " tests"); + } + + private void checkForErrors() { + if (errors > 0) + throw new RuntimeException("Failed " + errors + " tests"); + } + + private void errorIfTrue(boolean predicate, String errMessage) { + if (predicate) { + errors++; + System.err.println(errMessage); + } + } + + private void abortIfTrue(boolean predicate, String errMessage) { + if (predicate) { + throw new RuntimeException(errMessage); + } + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({METHOD, CONSTRUCTOR}) + @interface ExpectedParameterInfo { + int parameterCount() default 0; + Class[] parameterTypes() default {}; + ParameterizedInfo[] parameterizedTypes() default {}; + boolean isVarArgs() default false; + } + + @Target({}) + @interface ParameterizedInfo { + Class value() default Class.class; + String string() default ""; } public class Foo { int thing; + @ExpectedParameterInfo(parameterCount = 6, + parameterTypes = + {int.class, Foo.class, + List.class, List.class, + List.class, String[].class}, + parameterizedTypes = + {@ParameterizedInfo(Class.class), + @ParameterizedInfo(Class.class), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(Class.class)}, + isVarArgs = true) public void qux(int quux, Foo quuux, List l, List l2, List l3, String... rest) {} public class Inner { int thang; + @ExpectedParameterInfo(parameterCount = 2, + parameterTypes = {Foo.class, int.class}) public Inner(int theng) { thang = theng + thing; } } } - } diff --git a/jdk/test/java/net/Socket/asyncClose/Race.java b/jdk/test/java/net/Socket/asyncClose/Race.java new file mode 100644 index 00000000000..f8869394b3d --- /dev/null +++ b/jdk/test/java/net/Socket/asyncClose/Race.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006395 + * @summary Race in async socket close on Linux + */ + +import java.io.InputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.util.concurrent.Phaser; + +// Racey test, will not always fail, but if it does then we have a problem. + +public class Race { + final static int THREADS = 100; + + public static void main(String[] args) throws Exception { + try (ServerSocket ss = new ServerSocket(0)) { + final int port = ss.getLocalPort(); + final Phaser phaser = new Phaser(THREADS + 1); + for (int i=0; i<100; i++) { + final Socket s = new Socket("localhost", port); + s.setSoLinger(false, 0); + try (Socket sa = ss.accept()) { + sa.setSoLinger(false, 0); + final InputStream is = s.getInputStream(); + Thread[] threads = new Thread[THREADS]; + for (int j=0; j 0 && args[0] != null) { - urls = args[0]; - } + List entries = new ArrayList<>(); + entries.addAll(Arrays.asList(fileURLs)); + entries.addAll(Arrays.asList(jarURLs)); + entries.addAll(Arrays.asList(normalHttpURLs)); + entries.addAll(Arrays.asList(abnormalHttpURLs)); + if (hasFtp()) + entries.addAll(Arrays.asList(ftpURLs)); + URL url; - File f = new File(urls); - InputStream file = new FileInputStream(f); - BufferedReader in = new BufferedReader(new InputStreamReader(file)); - while(true) { - String context = in.readLine(); - if (context == null) { - break; - } - context = getValue(context); - String spec = getValue(in.readLine()); - String expected = getValue(in.readLine()); + for (Entry e : entries) { + if (e.context == null) + url = new URL(e.spec); + else + url = new URL(new URL(e.context), e.spec); - if (context.equals("null")) { - url = new URL(spec); - } else { - url = new URL(new URL(context), spec); - } - if (!(url.toString().equals(expected))) { - throw new RuntimeException("error for: \n\tURL:" + context + - "\n\tspec: " + spec + - "\n\texpected: " + expected + + if (!(url.toString().equals(e.expected))) { + throw new RuntimeException("error for: \n\tURL:" + e.context + + "\n\tspec: " + e.spec + + "\n\texpected: " + e.expected + "\n\tactual: " + url.toString()); } else { - System.out.println("success for: " + url + "\n"); + //debug + //System.out.println("success for: " + url); } - in.readLine(); } - in.close(); } - private static String getValue(String value) { - return value.substring(value.indexOf(':') + 2); + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } } + + static class Entry { + final String context; + final String spec; + final String expected; + Entry(String context, String spec, String expected) { + this.context = context; + this.spec =spec; + this.expected = expected; + } + } + + static Entry[] fileURLs = new Entry[] { + new Entry(null, + "file://JavaSoft/Test", + "file://JavaSoft/Test"), + new Entry(null, + "file:///JavaSoft/Test", + "file:/JavaSoft/Test"), + new Entry(null, + "file:/JavaSoft/Test", + "file:/JavaSoft/Test"), + new Entry(null, + "file:/c:/JavaSoft/Test", + "file:/c:/JavaSoft/Test"), + new Entry(null, + "file:/c:/JavaSoft/Test:something", + "file:/c:/JavaSoft/Test:something"), + new Entry(null, + "file:/c:/JavaSoft/Test#anchor", + "file:/c:/JavaSoft/Test#anchor"), + new Entry("file://JavaSoft/Test", + "Test#bar", + "file://JavaSoft/Test#bar"), + new Entry("file://codrus/c:/jdk/eng/index.html", + "pulsar.html", + "file://codrus/c:/jdk/eng/pulsar.html"), + new Entry("file:///c:/jdk/eng/index.html", + "pulsar.html", + "file:/c:/jdk/eng/pulsar.html"), + new Entry("file:///jdk/eng/index.html", + "pulsar.html", + "file:/jdk/eng/pulsar.html"), + new Entry("file://JavaSoft/Test", + "file://radartoad.com/Test#bar", + "file://radartoad.com/Test#bar"), + new Entry("file://JavaSoft/Test", + "/c:/Test#bar", + "file://JavaSoft/c:/Test#bar"), + }; + + static Entry[] jarURLs = new Entry[] { + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/", + "jar:http://www.foo.com/dir1/jar.jar!/"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/", + "jar:http://www.foo.com/dir1/jar.jar!/"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt", + "/dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/", + "dir4/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo.txt", + "#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo/bar/", + "baz/quux#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor"), + new Entry("jar:http://balloo.com/olle.jar!/", + "p2", + "jar:http://balloo.com/olle.jar!/p2") + }; + + static Entry[] normalHttpURLs = new Entry[] { + new Entry("http://a/b/c/d;p?q", "g", "http://a/b/c/g"), + new Entry("http://a/b/c/d;p?q", "./g", "http://a/b/c/g"), + new Entry("http://a/b/c/d;p?q", "g/", "http://a/b/c/g/"), + new Entry("http://a/b/c/d;p?q", "/g", "http://a/g"), + new Entry("http://a/b/c/d;p?q", "//g", "http://g"), + new Entry("http://a/b/c/d;p?q", "?y", "http://a/b/c/?y"), + new Entry("http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y"), + new Entry("http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s"), + new Entry("http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s"), + new Entry("http://a/b/c/d;p?q", ";x", "http://a/b/c/;x"), + new Entry("http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x"), + new Entry("http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s"), + new Entry("http://a/b/c/d;p?q", ".", "http://a/b/c/"), + new Entry("http://a/b/c/d;p?q", "./", "http://a/b/c/"), + new Entry("http://a/b/c/d;p?q", "..", "http://a/b/"), + new Entry("http://a/b/c/d;p?q", "../", "http://a/b/"), + new Entry("http://a/b/c/d;p?q", "../g", "http://a/b/g"), + new Entry("http://a/b/c/d;p?q", "../..", "http://a/"), + new Entry("http://a/b/c/d;p?q", "../../", "http://a/"), + new Entry("http://a/b/c/d;p?q", "../../g", "http://a/g"), + new Entry(null, + "http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc", + "http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc") + }; + + static Entry[] abnormalHttpURLs = new Entry[] { + new Entry("http://a/b/c/d;p?q", "../../../g", "http://a/../g"), + new Entry("http://a/b/c/d;p?q", "../../../../g", "http://a/../../g"), + new Entry("http://a/b/c/d;p?q", "/./g", "http://a/./g"), + new Entry("http://a/b/c/d;p?q", "/../g", "http://a/../g"), + new Entry("http://a/b/c/d;p?q", ".g", "http://a/b/c/.g"), + new Entry("http://a/b/c/d;p?q", "g.", "http://a/b/c/g."), + new Entry("http://a/b/c/d;p?q", "./../g", "http://a/b/g"), + new Entry("http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/"), + new Entry("http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h"), + new Entry("http://a/b/c/d;p?q", "g;x=1/./y", "http://a/b/c/g;x=1/y"), + new Entry("http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y") + }; + + static Entry[] ftpURLs = new Entry[] { + new Entry(null, + "ftp://ftp.foo.com/dir1/entry.txt", + "ftp://ftp.foo.com/dir1/entry.txt"), + new Entry(null, + "ftp://br:pwd@ftp.foo.com/dir1/jar.jar", + "ftp://br:pwd@ftp.foo.com/dir1/jar.jar"), + new Entry("ftp://ftp.foo.com/dir1/foo.txt", + "bar.txt", + "ftp://ftp.foo.com/dir1/bar.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "/entry.txt", + "ftp://ftp.foo.com/entry.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "dir1/entry.txt", + "ftp://ftp.foo.com/dir1/dir1/entry.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "/dir1/entry.txt", + "ftp://ftp.foo.com/dir1/entry.txt"), + new Entry("ftp://br:pwd@ftp.foo.com/dir1/jar.jar", + "/dir1/entry.txt", + "ftp://br:pwd@ftp.foo.com/dir1/entry.txt") + }; } diff --git a/jdk/test/java/net/URL/HandlerLoop.java b/jdk/test/java/net/URL/HandlerLoop.java index 69ca4e523b5..df02891b038 100644 --- a/jdk/test/java/net/URL/HandlerLoop.java +++ b/jdk/test/java/net/URL/HandlerLoop.java @@ -36,7 +36,7 @@ public class HandlerLoop { public static void main(String args[]) throws Exception { URL.setURLStreamHandlerFactory( new HandlerFactory("sun.net.www.protocol")); - URL url = new URL("file://bogus/index.html"); + URL url = new URL("file:///bogus/index.html"); System.out.println("url = " + url); url.openConnection(); } diff --git a/jdk/test/java/net/URL/Test.java b/jdk/test/java/net/URL/Test.java index 4ea4bd7c634..1e44ffe8b03 100644 --- a/jdk/test/java/net/URL/Test.java +++ b/jdk/test/java/net/URL/Test.java @@ -310,7 +310,14 @@ public class Test { throw new RuntimeException("Test failed"); } - + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } // -- Tests -- @@ -319,8 +326,9 @@ public class Test { header("RFC2396: Basic examples"); - test("ftp://ftp.is.co.za/rfc/rfc1808.txt") - .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); + if (hasFtp()) + test("ftp://ftp.is.co.za/rfc/rfc1808.txt") + .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); test("http://www.math.uio.no/faq/compression-faq/part1.html") .s("http").h("www.math.uio.no").p("/faq/compression-faq/part1.html").z(); @@ -328,8 +336,9 @@ public class Test { test("http://www.w3.org/Addressing/") .s("http").h("www.w3.org").p("/Addressing/").z(); - test("ftp://ds.internic.net/rfc/") - .s("ftp").h("ds.internic.net").p("/rfc/").z(); + if (hasFtp()) + test("ftp://ds.internic.net/rfc/") + .s("ftp").h("ds.internic.net").p("/rfc/").z(); test("http://www.ics.uci.edu/pub/ietf/url/historical.html#WARNING") .s("http").h("www.ics.uci.edu").p("/pub/ietf/url/historical.html") diff --git a/jdk/test/java/net/URL/URIToURLTest.java b/jdk/test/java/net/URL/URIToURLTest.java index 8ae07b36b12..79273b246c5 100644 --- a/jdk/test/java/net/URL/URIToURLTest.java +++ b/jdk/test/java/net/URL/URIToURLTest.java @@ -28,20 +28,22 @@ */ import java.net.*; +import java.util.ArrayList; +import java.util.List; public class URIToURLTest { public static void main(String args[]) throws Exception { - String[] uris = { - "http://jag:cafebabe@java.sun.com:94/b/c/d?q#g", - "http://[1080:0:0:0:8:800:200C:417A]/index.html", - "http://a/b/c/d;p?q", - "ftp://ftp.is.co.za/rfc/rfc1808.txt", - "mailto:mduerst@ifi.unizh.ch", // opaque url - "http:comp.infosystems.www.servers.unix" //opaque url - }; + List uris = new ArrayList<>(); + uris.add("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g"); + uris.add("http://[1080:0:0:0:8:800:200C:417A]/index.html"); + uris.add("http://a/b/c/d;p?q"); + uris.add("mailto:mduerst@ifi.unizh.ch"); + uris.add("http:comp.infosystems.www.servers.unix"); + if (hasFtp()) + uris.add("ftp://ftp.is.co.za/rfc/rfc1808.txt"); - for (int i = 0; i < uris.length; i++) { - URI uri = new URI(uris[i]); + for (String uriStr : uris) { + URI uri = new URI(uriStr); URL url = uri.toURL(); String scheme = uri.getScheme(); boolean schemeCheck = scheme == null? url.getProtocol() == null : @@ -111,4 +113,13 @@ public class URIToURLTest { url.getRef()); } } + + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } } diff --git a/jdk/test/java/net/URL/abnormal_http_urls b/jdk/test/java/net/URL/abnormal_http_urls deleted file mode 100644 index 1fbf57d37a5..00000000000 --- a/jdk/test/java/net/URL/abnormal_http_urls +++ /dev/null @@ -1,43 +0,0 @@ -URL: http://a/b/c/d;p?q -spec: ../../../g -expected: http://a/../g - -URL: http://a/b/c/d;p?q -spec: ../../../../g -expected: http://a/../../g - -URL: http://a/b/c/d;p?q -spec: /./g -expected: http://a/./g - -URL: http://a/b/c/d;p?q -spec: /../g -expected: http://a/../g - -URL: http://a/b/c/d;p?q -spec: .g -expected: http://a/b/c/.g - -URL: http://a/b/c/d;p?q -spec: g. -expected: http://a/b/c/g. - -URL: http://a/b/c/d;p?q -spec: ./../g -expected: http://a/b/g - -URL: http://a/b/c/d;p?q -spec: ./g/. -expected: http://a/b/c/g/ - -URL: http://a/b/c/d;p?q -spec: g/./h -expected: http://a/b/c/g/h - -URL: http://a/b/c/d;p?q -spec: g;x=1/./y -expected: http://a/b/c/g;x=1/y - -URL: http://a/b/c/d;p?q -spec: g;x=1/../y -expected: http://a/b/c/y diff --git a/jdk/test/java/net/URL/ftp_urls b/jdk/test/java/net/URL/ftp_urls deleted file mode 100644 index 1f8d6fc6fa6..00000000000 --- a/jdk/test/java/net/URL/ftp_urls +++ /dev/null @@ -1,27 +0,0 @@ -URL: null -spec: ftp://ftp.foo.com/dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/entry.txt - -URL: null -spec: ftp://br:pwd@ftp.foo.com/dir1/jar.jar -expected: ftp://br:pwd@ftp.foo.com/dir1/jar.jar - -URL: ftp://ftp.foo.com/dir1/foo.txt -spec: bar.txt -expected: ftp://ftp.foo.com/dir1/bar.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: /entry.txt -expected: ftp://ftp.foo.com/entry.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/dir1/entry.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: /dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/entry.txt - -URL: ftp://br:pwd@ftp.foo.com/dir1/jar.jar -spec: /dir1/entry.txt -expected: ftp://br:pwd@ftp.foo.com/dir1/entry.txt diff --git a/jdk/test/java/net/URL/jar_urls b/jdk/test/java/net/URL/jar_urls deleted file mode 100644 index ebd888450fa..00000000000 --- a/jdk/test/java/net/URL/jar_urls +++ /dev/null @@ -1,75 +0,0 @@ -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/ -expected: jar:http://www.foo.com/dir1/jar.jar!/ - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/ -expected: jar:http://www.foo.com/dir1/jar.jar!/ - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir1/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt -spec: /dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/ -spec: dir4/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor - -URL: jar:http://www.foo.com/dir1/jar.jar!/foo.txt -spec: #anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor - -URL: jar:http://www.foo.com/dir1/jar.jar!/foo/bar/ -spec: baz/quux#anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor - -URL: jar:http://balloo.com/olle.jar!/ -spec: p2 -expected: jar:http://balloo.com/olle.jar!/p2 diff --git a/jdk/test/java/net/URL/normal_http_urls b/jdk/test/java/net/URL/normal_http_urls deleted file mode 100644 index 52d332057dd..00000000000 --- a/jdk/test/java/net/URL/normal_http_urls +++ /dev/null @@ -1,83 +0,0 @@ -URL: http://a/b/c/d;p?q -spec: g -expected: http://a/b/c/g - -URL: http://a/b/c/d;p?q -spec: ./g -expected: http://a/b/c/g - -URL: http://a/b/c/d;p?q -spec: g/ -expected: http://a/b/c/g/ - -URL: http://a/b/c/d;p?q -spec: /g -expected: http://a/g - -URL: http://a/b/c/d;p?q -spec: //g -expected: http://g - -URL: http://a/b/c/d;p?q -spec: ?y -expected: http://a/b/c/?y - -URL: http://a/b/c/d;p?q -spec: g?y -expected: http://a/b/c/g?y - -URL: http://a/b/c/d;p?q -spec: g#s -expected: http://a/b/c/g#s - -URL: http://a/b/c/d;p?q -spec: g?y#s -expected: http://a/b/c/g?y#s - -URL: http://a/b/c/d;p?q -spec: ;x -expected: http://a/b/c/;x - -URL: http://a/b/c/d;p?q -spec: g;x -expected: http://a/b/c/g;x - -URL: http://a/b/c/d;p?q -spec: g;x?y#s -expected: http://a/b/c/g;x?y#s - -URL: http://a/b/c/d;p?q -spec: . -expected: http://a/b/c/ - -URL: http://a/b/c/d;p?q -spec: ./ -expected: http://a/b/c/ - -URL: http://a/b/c/d;p?q -spec: .. -expected: http://a/b/ - -URL: http://a/b/c/d;p?q -spec: ../ -expected: http://a/b/ - -URL: http://a/b/c/d;p?q -spec: ../g -expected: http://a/b/g - -URL: http://a/b/c/d;p?q -spec: ../.. -expected: http://a/ - -URL: http://a/b/c/d;p?q -spec: ../../ -expected: http://a/ - -URL: http://a/b/c/d;p?q -spec: ../../g -expected: http://a/g - -URL: null -spec: http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc -expected: http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc diff --git a/jdk/test/java/net/URL/runconstructor.sh b/jdk/test/java/net/URL/runconstructor.sh deleted file mode 100644 index f64fd8509d1..00000000000 --- a/jdk/test/java/net/URL/runconstructor.sh +++ /dev/null @@ -1,67 +0,0 @@ -# -# Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 4393671 -# @summary URL constructor URL(URL context, String spec) FAILED with specific input in merlin -# -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin ) - PS=":" - FS="/" - ;; - CYGWIN* ) - PS=";" - FS="/" - ;; - Windows* ) - PS=";" - FS="\\" - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac -${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \ - ${TESTSRC}${FS}Constructor.java - -failures=0 - -go() { - echo '' - ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} Constructor $1 - if [ $? != 0 ]; then failures=`expr $failures + 1`; fi -} - -go ${TESTSRC}${FS}share_file_urls -go ${TESTSRC}${FS}jar_urls -go ${TESTSRC}${FS}normal_http_urls -go ${TESTSRC}${FS}ftp_urls -go ${TESTSRC}${FS}abnormal_http_urls - -if [ "$failures" != "0" ]; then - echo $failures tests failed - exit 1; -fi diff --git a/jdk/test/java/net/URL/share_file_urls b/jdk/test/java/net/URL/share_file_urls deleted file mode 100644 index 48451b45db4..00000000000 --- a/jdk/test/java/net/URL/share_file_urls +++ /dev/null @@ -1,51 +0,0 @@ -URL: null -spec: file://JavaSoft/Test -expected: file://JavaSoft/Test - -URL: null -spec: file:///JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: null -spec: file:/JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: null -spec: file:/c:/JavaSoft/Test -expected: file:/c:/JavaSoft/Test - -URL: null -spec: file:/c:/JavaSoft/Test:something -expected: file:/c:/JavaSoft/Test:something - -URL: null -spec: file:/c:/JavaSoft/Test#anchor -expected: file:/c:/JavaSoft/Test#anchor - -URL: null -spec: file:/JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: file://JavaSoft/Test -spec: Test#bar -expected: file://JavaSoft/Test#bar - -URL: file://codrus/c:/jdk/eng/index.html -spec: pulsar.html -expected: file://codrus/c:/jdk/eng/pulsar.html - -URL: file:///c:/jdk/eng/index.html -spec: pulsar.html -expected: file:/c:/jdk/eng/pulsar.html - -URL: file:///jdk/eng/index.html -spec: pulsar.html -expected: file:/jdk/eng/pulsar.html - -URL: file://JavaSoft/Test -spec: file://radartoad.com/Test#bar -expected: file://radartoad.com/Test#bar - -URL: file://JavaSoft/Test -spec: /c:/Test#bar -expected: file://JavaSoft/c:/Test#bar \ No newline at end of file diff --git a/jdk/test/java/net/URL/win32_file_urls b/jdk/test/java/net/URL/win32_file_urls deleted file mode 100644 index 7e3981c1490..00000000000 --- a/jdk/test/java/net/URL/win32_file_urls +++ /dev/null @@ -1,15 +0,0 @@ -URL: null -spec: file://c:\JavaSoft\Test -expected: file://c:/JavaSoft/Test - -URL: null -spec: file:/c:\JavaSoft\Test -expected: file:/c:/JavaSoft/Test - -URL: null -spec: file:/c:\JavaSoft\Test:something#anchor -expected: file:/c:/JavaSoft/Test:something#anchor - -URL: file:///c:\jdk\eng\index.html -spec: pulsar.html -expected: file:/c:/jdk/eng/pulsar.html \ No newline at end of file diff --git a/jdk/test/java/net/URLConnection/RequestProperties.java b/jdk/test/java/net/URLConnection/RequestProperties.java index 74fd558ddbe..af549e22e54 100644 --- a/jdk/test/java/net/URLConnection/RequestProperties.java +++ b/jdk/test/java/net/URLConnection/RequestProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -28,90 +28,55 @@ */ import java.net.*; +import java.util.ArrayList; +import java.util.List; public class RequestProperties { - public static void main (String args[]) throws Exception { - URL url0 = new URL ("http://foo.com/bar/"); - URL url1 = new URL ("file:/etc/passwd"); - URL url2 = new URL ("ftp://foo:bar@foobar.com/etc/passwd"); - URL url3 = new URL ("jar:http://foo.com/bar.html!/foo/bar"); - URLConnection urlc0 = url0.openConnection (); - URLConnection urlc1 = url1.openConnection (); - URLConnection urlc2 = url2.openConnection (); - URLConnection urlc3 = url3.openConnection (); - int count = 0; - String s = null; - try { - urlc0.setRequestProperty (null, null); - System.out.println ("http: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc0.addRequestProperty (null, null); - System.out.println ("http: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc1.setRequestProperty (null, null); - System.out.println ("file: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc1.addRequestProperty (null, null); - System.out.println ("file: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc2.setRequestProperty (null, null); - System.out.println ("ftp: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc2.addRequestProperty (null, null); - System.out.println ("ftp: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc3.setRequestProperty (null, null); - System.out.println ("jar: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc3.addRequestProperty (null, null); - System.out.println ("jar: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - if (urlc0.getRequestProperty (null) != null) { - System.out.println ("http: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc1.getRequestProperty (null) != null) { - System.out.println ("file: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc2.getRequestProperty (null) != null) { - System.out.println ("ftp: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc2.getRequestProperty (null) != null) { - System.out.println ("jar: getRequestProperty (null,) did not return null"); - } else { - count ++; - } + static int failed; - if (count != 12) { - throw new RuntimeException ((12 -count) + " errors") ; + public static void main (String args[]) throws Exception { + List urls = new ArrayList<>(); + urls.add("http://foo.com/bar/"); + urls.add("jar:http://foo.com/bar.html!/foo/bar"); + urls.add("file:/etc/passwd"); + if (hasFtp()) + urls.add("ftp://foo:bar@foobar.com/etc/passwd"); + + for (String urlStr : urls) + test(new URL(urlStr)); + + if (failed != 0) + throw new RuntimeException(failed + " errors") ; + } + + static void test(URL url) throws Exception { + URLConnection urlc = url.openConnection(); + try { + urlc.setRequestProperty(null, null); + System.out.println(url.getProtocol() + + ": setRequestProperty(null,) did not throw NPE"); + failed++; + } catch (NullPointerException e) { /* Expected */ } + try { + urlc.addRequestProperty(null, null); + System.out.println(url.getProtocol() + + ": addRequestProperty(null,) did not throw NPE"); + failed++; + } catch (NullPointerException e) { /* Expected */ } + + if (urlc.getRequestProperty(null) != null) { + System.out.println(url.getProtocol() + + ": getRequestProperty(null,) did not return null"); + failed++; + } + } + + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; } } } diff --git a/jdk/test/java/net/URLConnection/RequestPropertyValues.java b/jdk/test/java/net/URLConnection/RequestPropertyValues.java index 77bb469e672..6874063ca1d 100644 --- a/jdk/test/java/net/URLConnection/RequestPropertyValues.java +++ b/jdk/test/java/net/URLConnection/RequestPropertyValues.java @@ -27,8 +27,11 @@ * @summary Test URLConnection Request Proterties */ +import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; /** * Part1: @@ -45,28 +48,29 @@ public class RequestPropertyValues { } public static void part1() throws Exception { - URL[] urls = { new URL("http://localhost:8088"), - new URL("file:/etc/passwd"), - new URL("ftp://foo:bar@foobar.com/etc/passwd"), - new URL("jar:http://foo.com/bar.html!/foo/bar") - }; + List urls = new ArrayList<>(); + urls.add(new URL("http://localhost:8088")); + urls.add(new URL("file:/etc/passwd")); + urls.add(new URL("jar:http://foo.com/bar.html!/foo/bar")); + if (hasFtp()) + urls.add(new URL("ftp://foo:bar@foobar.com/etc/passwd")); boolean failed = false; - for (int proto = 0; proto < urls.length; proto++) { - URLConnection uc = (URLConnection) urls[proto].openConnection(); + for (URL url : urls) { + URLConnection uc = url.openConnection(); try { uc.setRequestProperty("TestHeader", null); } catch (NullPointerException npe) { System.out.println("setRequestProperty is throwing NPE" + - " for url: " + urls[proto]); + " for url: " + url); failed = true; } try { uc.addRequestProperty("TestHeader", null); } catch (NullPointerException npe) { System.out.println("addRequestProperty is throwing NPE" + - " for url: " + urls[proto]); + " for url: " + url); failed = true; } } @@ -110,4 +114,12 @@ public class RequestPropertyValues { } } + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } } diff --git a/jdk/test/java/security/KeyStore/PBETest.java b/jdk/test/java/security/KeyStore/PBETest.java index be437d03bbd..2186165ea68 100644 --- a/jdk/test/java/security/KeyStore/PBETest.java +++ b/jdk/test/java/security/KeyStore/PBETest.java @@ -58,45 +58,46 @@ public class PBETest { new File(NEW_KEYSTORE).delete(); - try { - KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD); - KeyStore.Entry entry = - keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry named '" + ALIAS + "'"); - - // Set entry - KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null); - keystore2.setEntry(ALIAS, entry, - new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO, - new PBEParameterSpec(SALT, ITERATION_COUNT, - new IvParameterSpec(IV)))); - System.out.println("Encrypted entry using: " + PBE_ALGO); - - System.out.println("Storing keystore to: " + NEW_KEYSTORE); - keystore2.store(new FileOutputStream(NEW_KEYSTORE), PASSWORD); - - keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD); - entry = keystore2.getEntry(ALIAS, + KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD); + KeyStore.Entry entry = + keystore.getEntry(ALIAS, new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry named '" + ALIAS + "'"); + System.out.println("Retrieved entry named '" + ALIAS + "'"); - } finally { - new File(NEW_KEYSTORE).delete(); - System.out.println("Deleted keystore: " + NEW_KEYSTORE); + // Set entry + KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null); + keystore2.setEntry(ALIAS, entry, + new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO, + new PBEParameterSpec(SALT, ITERATION_COUNT, + new IvParameterSpec(IV)))); + System.out.println("Encrypted entry using: " + PBE_ALGO); + + try (FileOutputStream outStream = new FileOutputStream(NEW_KEYSTORE)) { + System.out.println("Storing keystore to: " + NEW_KEYSTORE); + keystore2.store(outStream, PASSWORD); } + + keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD); + entry = keystore2.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + System.out.println("Retrieved entry named '" + ALIAS + "'"); } private static KeyStore load(String type, String path, char[] password) throws Exception { - - FileInputStream stream = null; - if (path != null) { - stream = new FileInputStream(path); - } KeyStore keystore = KeyStore.getInstance(type); - System.out.println("Loading keystore from: " + path); - keystore.load(stream, password); + + if (path != null) { + + try (FileInputStream inStream = new FileInputStream(path)) { + System.out.println("Loading keystore from: " + path); + keystore.load(inStream, password); + System.out.println("Loaded keystore with " + keystore.size() + + " entries"); + } + } else { + keystore.load(null, null); + } return keystore; } diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java index 6b37772d7f6..e0af4de23b7 100644 --- a/jdk/test/java/util/Base64/TestBase64.java +++ b/jdk/test/java/util/Base64/TestBase64.java @@ -22,7 +22,7 @@ */ /** - * @test 4235519 8004212 + * @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530 * @summary tests java.util.Base64 */ @@ -109,6 +109,15 @@ public class TestBase64 { // test return value from decode(ByteBuffer, ByteBuffer) testDecBufRet(); + + // test single-non-base64 character for mime decoding + testSingleNonBase64MimeDec(); + + // test decoding of unpadded data + testDecodeUnpadded(); + + // test mime decoding with ignored character after padding + testDecodeIgnoredAfterPadding(); } private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder(); @@ -295,6 +304,7 @@ public class TestBase64 { checkNull(new Runnable() { public void run() { enc.encode(bb_null); }}); checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }}); checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }}); + checkNull(new Runnable() { public void run() { enc.wrap(null); }}); } private static void testNull(final Base64.Decoder dec) { @@ -305,6 +315,7 @@ public class TestBase64 { checkNull(new Runnable() { public void run() { dec.decode(bb_null); }}); checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }}); checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }}); + checkNull(new Runnable() { public void run() { dec.wrap(null); }}); } private static interface Testable { @@ -354,6 +365,94 @@ public class TestBase64 { } catch (IllegalArgumentException iae) {} } + private static void testDecodeIgnoredAfterPadding() throws Throwable { + for (byte nonBase64 : new byte[] {'#', '(', '!', '\\', '-', '_', '\n', '\r'}) { + byte[][] src = new byte[][] { + "A".getBytes("ascii"), + "AB".getBytes("ascii"), + "ABC".getBytes("ascii"), + "ABCD".getBytes("ascii"), + "ABCDE".getBytes("ascii") + }; + Base64.Encoder encM = Base64.getMimeEncoder(); + Base64.Decoder decM = Base64.getMimeDecoder(); + Base64.Encoder enc = Base64.getEncoder(); + Base64.Decoder dec = Base64.getDecoder(); + for (int i = 0; i < src.length; i++) { + // decode(byte[]) + byte[] encoded = encM.encode(src[i]); + encoded = Arrays.copyOf(encoded, encoded.length + 1); + encoded[encoded.length - 1] = nonBase64; + checkEqual(decM.decode(encoded), src[i], "Non-base64 char is not ignored"); + try { + dec.decode(encoded); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + + // decode(ByteBuffer[], ByteBuffer[]) + ByteBuffer encodedBB = ByteBuffer.wrap(encoded); + ByteBuffer decodedBB = ByteBuffer.allocate(100); + int ret = decM.decode(encodedBB, decodedBB); + byte[] buf = new byte[ret]; + decodedBB.flip(); + decodedBB.get(buf); + checkEqual(buf, src[i], "Non-base64 char is not ignored"); + try { + encodedBB.rewind(); + decodedBB.clear(); + dec.decode(encodedBB, decodedBB); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + // direct + encodedBB.rewind(); + decodedBB = ByteBuffer.allocateDirect(100); + ret = decM.decode(encodedBB, decodedBB); + buf = new byte[ret]; + decodedBB.flip(); + decodedBB.get(buf); + checkEqual(buf, src[i], "Non-base64 char is not ignored"); + try { + encodedBB.rewind(); + decodedBB.clear(); + dec.decode(encodedBB, decodedBB); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + } + } + } + + private static void testDecodeUnpadded() throws Throwable { + byte[] srcA = new byte[] { 'Q', 'Q' }; + byte[] srcAA = new byte[] { 'Q', 'Q', 'E'}; + Base64.Decoder dec = Base64.getDecoder(); + byte[] ret = dec.decode(srcA); + if (ret[0] != 'A') + throw new RuntimeException("Decoding unpadding input A failed"); + ret = dec.decode(srcAA); + if (ret[0] != 'A' && ret[1] != 'A') + throw new RuntimeException("Decoding unpadding input AA failed"); + ret = new byte[10]; + if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 1 && + ret[0] != 'A') + throw new RuntimeException("Decoding unpadding input A from stream failed"); + if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 2 && + ret[0] != 'A' && ret[1] != 'A') + throw new RuntimeException("Decoding unpadding input AA from stream failed"); + } + + // single-non-base64-char should be ignored for mime decoding, but + // iae for basic decoding + private static void testSingleNonBase64MimeDec() throws Throwable { + for (String nonBase64 : new String[] {"#", "(", "!", "\\", "-", "_"}) { + if (Base64.getMimeDecoder().decode(nonBase64).length != 0) { + throw new RuntimeException("non-base64 char is not ignored"); + } + try { + Base64.getDecoder().decode(nonBase64); + throw new RuntimeException("No IAE for single non-base64 char"); + } catch (IllegalArgumentException iae) {} + } + } private static void testDecBufRet() throws Throwable { Random rnd = new java.util.Random(); diff --git a/jdk/test/java/util/Formatter/Basic-X.java.template b/jdk/test/java/util/Formatter/Basic-X.java.template index 55b24097f6e..831c49212f0 100644 --- a/jdk/test/java/util/Formatter/Basic-X.java.template +++ b/jdk/test/java/util/Formatter/Basic-X.java.template @@ -1103,6 +1103,15 @@ public class Basic$Type$ extends Basic { test("%.5f", "1.99999", val); test("%.6f", "1.999990", val); + val = new BigDecimal(0.9996); + test("%.0f", "1", val); + test("%.1f", "1.0", val); + test("%.2f", "1.00", val); + test("%.3f", "1.000", val); + test("%.4f", "0.9996", val); + test("%.5f", "0.99960", val); + test("%.6f", "0.999600", val); + #end[BigDecimal] #if[float] diff --git a/jdk/test/java/util/Formatter/BasicBigDecimal.java b/jdk/test/java/util/Formatter/BasicBigDecimal.java index afc446ae4b0..6f36201aa34 100644 --- a/jdk/test/java/util/Formatter/BasicBigDecimal.java +++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java @@ -1102,6 +1102,15 @@ public class BasicBigDecimal extends Basic { test("%.4f", "2.0000", val); test("%.5f", "1.99999", val); test("%.6f", "1.999990", val); + + val = new BigDecimal(0.9996); + test("%.0f", "1", val); + test("%.1f", "1.0", val); + test("%.2f", "1.00", val); + test("%.3f", "1.000", val); + test("%.4f", "0.9996", val); + test("%.5f", "0.99960", val); + test("%.6f", "0.999600", val); diff --git a/jdk/test/java/util/HashMap/HashMapCloneLeak.java b/jdk/test/java/util/HashMap/HashMapCloneLeak.java new file mode 100644 index 00000000000..2a5fcaa4f1c --- /dev/null +++ b/jdk/test/java/util/HashMap/HashMapCloneLeak.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 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. + */ + +/** + * @test + * @bug 7042126 + * @summary Verify that we do not leak contents when we clone a HashMap + * @author david.buck@oracle.com + * @run main/othervm HashMapCloneLeak + * @run main/othervm -XX:+AggressiveOpts HashMapCloneLeak + */ + +import java.util.HashMap; +import java.lang.ref.WeakReference; + +public class HashMapCloneLeak { + + static WeakReference wr = null; + + // helper method to keep testObject and map out of main method's scope + private static HashMap makeMap() { + HashMap map = new HashMap(); + Object testObject = new Object(); + wr = new WeakReference(testObject); + map.put(42, testObject); + return map; + } + + public static void main(String[] args) throws Exception { + HashMap hm = makeMap(); + hm = (HashMap)hm.clone(); + hm.clear(); + // There should no longer be a strong reference to testObject + // the WeakReference should be nulled out by GC. If not, + // we will hang here until timed out by the test harness. + Object[] chain = null; + while (wr.get() != null) { + try { + Object[] allocate = new Object[1000000]; + allocate[0] = chain; + chain = allocate; + } catch (OutOfMemoryError oome) { + chain = null; + } + System.gc(); + Thread.sleep(100); + } + } + +} diff --git a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java index d5fd91e527f..db313040c25 100644 --- a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java +++ b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java @@ -31,6 +31,7 @@ import com.sun.jmx.remote.internal.ServerNotifForwarder; import java.io.IOException; import java.lang.management.ManagementFactory; +import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -86,20 +87,26 @@ public class DeadListenerTest { Map> listenerMap = (Map>) listenerMapF.get(serverNotifForwarder); assertTrue("Server listenerMap initially empty", mapWithoutKey(listenerMap, delegateName).isEmpty()); - CountListener count1 = new CountListener(); + final AtomicInteger count1Val = new AtomicInteger(); + CountListener count1 = new CountListener(count1Val); mbsc.addNotificationListener(name, count1, null, null); + WeakReference count1Ref = new WeakReference<>(count1); + count1 = null; - CountListener count2 = new CountListener(); + final AtomicInteger count2Val = new AtomicInteger(); + CountListener count2 = new CountListener(count2Val); NotificationFilterSupport dummyFilter = new NotificationFilterSupport(); dummyFilter.enableType(""); mbsc.addNotificationListener(name, count2, dummyFilter, "noddy"); + WeakReference count2Ref = new WeakReference<>(count2); + count2 = null; assertTrue("One entry in listenerMap for two listeners on same MBean", mapWithoutKey(listenerMap, delegateName).size() == 1); Set set = listenerMap.get(name); assertTrue("Set in listenerMap for MBean has two elements", set != null && set.size() == 2); - assertTrue("Initial value of count1 == 0", count1.count() == 0); - assertTrue("Initial value of count2 == 0", count2.count() == 0); + assertTrue("Initial value of count1 == 0", count1Val.get() == 0); + assertTrue("Initial value of count2 == 0", count2Val.get() == 0); Notification notif = new Notification("type", name, 0); @@ -107,11 +114,11 @@ public class DeadListenerTest { // Make sure notifs are working normally. long deadline = System.currentTimeMillis() + 2000; - while ((count1.count() != 1 || count2.count() != 1) && System.currentTimeMillis() < deadline) { + while ((count1Val.get() != 1 || count2Val.get() != 1) && System.currentTimeMillis() < deadline) { Thread.sleep(10); } - assertTrue("New value of count1 == 1", count1.count() == 1); - assertTrue("Initial value of count2 == 1", count2.count() == 1); + assertTrue("New value of count1 == 1", count1Val.get() == 1); + assertTrue("Initial value of count2 == 1", count2Val.get() == 1); // Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException CountListener count3 = new CountListener(); @@ -136,28 +143,29 @@ public class DeadListenerTest { mbs.unregisterMBean(name); mbean.sendNotification(notif); Thread.sleep(200); - assertTrue("New value of count1 == 1", count1.count() == 1); - assertTrue("Initial value of count2 == 1", count2.count() == 1); + + assertTrue("New value of count1 == 1", count1Val.get() == 1); + assertTrue("Initial value of count2 == 1", count2Val.get() == 1); + + // wait for the listener cleanup to take place upon processing notifications + int countdown = 50; // waiting max. 5 secs + while (countdown-- > 0 && + (count1Ref.get() != null || + count2Ref.get() != null)) { + System.gc(); + Thread.sleep(100); + System.gc(); + } + // listener has been removed or the wait has timed out + + assertTrue("count1 notification listener has not been cleaned up", count1Ref.get() == null); + assertTrue("count2 notification listener has not been cleaned up", count2Ref.get() == null); // Check that there is no trace of the listeners any more in ServerNotifForwarder.listenerMap. // THIS DEPENDS ON JMX IMPLEMENTATION DETAILS. // If the JMX implementation changes, the code here may have to change too. Set setForUnreg = listenerMap.get(name); assertTrue("No trace of unregistered MBean: " + setForUnreg, setForUnreg == null); - - // Remove attempts should fail. - try { - mbsc.removeNotificationListener(name, count1); - assertTrue("Remove of count1 listener should have failed", false); - } catch (ListenerNotFoundException e) { - // OK: expected - } - try { - mbsc.removeNotificationListener(name, count2, dummyFilter, "noddy"); - assertTrue("Remove of count2 listener should have failed", false); - } catch (ListenerNotFoundException e) { - // OK: expected - } } private static Map mapWithoutKey(Map map, K key) { @@ -173,6 +181,10 @@ public class DeadListenerTest { public static class CountListener implements NotificationListener { final AtomicInteger count; + public CountListener(AtomicInteger i) { + count = i; + } + public CountListener() { this.count = new AtomicInteger(); } diff --git a/jdk/test/sun/java2d/pipe/Test8004821.java b/jdk/test/sun/java2d/pipe/Test8004821.java new file mode 100644 index 00000000000..c2143dda308 --- /dev/null +++ b/jdk/test/sun/java2d/pipe/Test8004821.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 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.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.image.BufferedImage; + +/** + * @test + * @bug 8004821 + * @summary Verifies that drawPolygon() works with empty arrays. + * @author Sergey Bylokhov + */ +public final class Test8004821 { + + public static void main(final String[] args) { + final int[] arrEmpty = {}; + final int[] arr1elem = {150}; + final BufferedImage bi = new BufferedImage(300, 300, + BufferedImage.TYPE_INT_RGB); + final Graphics2D g = (Graphics2D) bi.getGraphics(); + test(g, arrEmpty); + test(g, arr1elem); + g.translate(2.0, 2.0); + test(g, arrEmpty); + test(g, arr1elem); + g.scale(2.0, 2.0); + test(g, arrEmpty); + test(g, arr1elem); + g.dispose(); + } + + private static void test(final Graphics2D g, final int[] arr) { + g.drawPolygon(arr, arr, arr.length); + g.drawPolygon(new Polygon(arr, arr, arr.length)); + g.fillPolygon(arr, arr, arr.length); + g.fillPolygon(new Polygon(arr, arr, arr.length)); + g.drawPolyline(arr, arr, arr.length); + } +} diff --git a/jdk/test/sun/management/jdp/JdpClient.java b/jdk/test/sun/management/jdp/JdpClient.java new file mode 100644 index 00000000000..4a2348468b2 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpClient.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.util.Collections; +import java.util.Enumeration; +import sun.management.jdp.JdpException; +import sun.management.jdp.JdpJmxPacket; + +public class JdpClient { + + private static class PacketListener implements Runnable { + + private static final int BUFFER_LENGTH = 4096; + private final DatagramChannel channel; + private static int maxPacketCount = 1; + private static int maxEmptyPacketCount = 10; + + + PacketListener(DatagramChannel channel) { + this.channel = channel; + } + + @java.lang.Override + public void run() { + try { + Selector sel; + sel = Selector.open(); + channel.configureBlocking(false); + channel.register(sel, SelectionKey.OP_READ); + ByteBuffer buf = ByteBuffer.allocate(1024); + + int count = 1; + int emptyPacketsCount = 1; + + try { + while (true) { + + sel.selectedKeys().clear(); + buf.rewind(); + + sel.select(10 * 1000); + channel.receive(buf); + + if (buf.position() == 0 ){ + if (JdpDoSomething.getVerbose()){ + System.err.println("Empty packet received"); + } + if (++emptyPacketsCount > maxEmptyPacketCount){ + throw new RuntimeException("Test failed, maxEmptyPacketCount reached"); + } + + continue; + } + + buf.flip(); + byte[] dgramData = new byte[buf.remaining()]; + buf.get(dgramData); + + try { + JdpJmxPacket packet = new JdpJmxPacket(dgramData); + JdpDoSomething.printJdpPacket(packet); + if(++count > maxPacketCount){ + break; + } + } catch (JdpException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed"); + } + + } + + System.out.println("OK: Test passed"); + + } finally { + sel.close(); + channel.close(); + } + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed"); + } + } + } + + public static void main(String[] args) { + try { + String discoveryPort = System.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = System.getProperty("com.sun.management.jdp.address"); + if (discoveryAddress == null || discoveryPort == null) { + System.out.println("Test failed. address and port must be specified"); + return; + } + + int port = Integer.parseInt(discoveryPort); + InetAddress address = InetAddress.getByName(discoveryAddress); + + + ProtocolFamily family = (address instanceof Inet6Address) + ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + + DatagramChannel channel; + + channel = DatagramChannel.open(family); + channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); + channel.bind(new InetSocketAddress(port)); + + Enumeration nets = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface interf : Collections.list(nets)) { + if (interf.supportsMulticast()) { + try { + channel.join(address, interf); + } catch (IOException e) { + // Skip not configured interfaces + } + } + } + + PacketListener listener = new PacketListener(channel); + new Thread(listener, "Jdp Client").start(); + + } catch (RuntimeException e){ + System.out.println("Test failed."); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Test failed. unexpected error " + e); + } + } +} diff --git a/jdk/test/sun/management/jdp/JdpDoSomething.java b/jdk/test/sun/management/jdp/JdpDoSomething.java new file mode 100644 index 00000000000..ad9366cbaa4 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpDoSomething.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Objects; + +import sun.management.jdp.JdpJmxPacket; +import sun.management.jdp.JdpException; + +public class JdpDoSomething { + + private static final String lockFileName = "JdpDoSomething.lck"; + private static final boolean verbose=false; + + public static boolean getVerbose(){ + return verbose; + } + + public static void printJdpPacket(JdpJmxPacket p) { + if (getVerbose()) { + try { + RandomAccessFile f = new RandomAccessFile("out.dmp", "rw"); + f.write(p.getPacketData()); + f.close(); + } catch (IOException e) { + System.out.println("Can't write a dump file: " + e); + } + + System.out.println("Id: " + p.getId()); + System.out.println("Jmx: " + p.getJmxServiceUrl()); + System.out.println("Main: " + p.getMainClass()); + System.out.println("InstanceName: " + p.getInstanceName()); + + System.out.flush(); + } + } + + public static void compaireJdpPacketEx(JdpJmxPacket p1, JdpJmxPacket p2) + throws JdpException { + + if (!Objects.equals(p1, p1)) { + throw new JdpException("Packet mismatch error"); + } + + if (!Objects.equals(p1.getMainClass(), p2.getMainClass())) { + throw new JdpException("Packet mismatch error (main class)"); + } + + if (!Objects.equals(p1.getInstanceName(), p2.getInstanceName())) { + throw new JdpException("Packet mismatch error (instance name)"); + } + } + + public static void doSomething() { + try { + File lockFile = new File(lockFileName); + lockFile.createNewFile(); + + while (lockFile.exists()) { + long datetime = lockFile.lastModified(); + long epoch = System.currentTimeMillis() / 1000; + + // Don't allow test app to run more than an hour + if (epoch - datetime > 3600) { + System.err.println("Lock is too old. Aborting"); + return; + } + Thread.sleep(1); + } + + } catch (Throwable e) { + System.err.println("Something bad happens:" + e); + } + } + + public static void main(String args[]) throws Exception { + System.err.println("main enter"); + doSomething(); + System.err.println("main exit"); + } +} diff --git a/jdk/test/sun/management/jdp/JdpTest.sh b/jdk/test/sun/management/jdp/JdpTest.sh new file mode 100644 index 00000000000..2aded729953 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpTest.sh @@ -0,0 +1,323 @@ +#!/bin/sh + +# Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +# @test +# @bug 7169888 +# @build JdpUnitTest JdpClient JdpDoSomething +# @run shell JdpTest.sh --jtreg --no-compile +# @summary No word Failed expected in the test output + +_verbose=no +_jtreg=no +_compile=yes + +# temporary disable jcmd related tests +# _testsuite="01,02,03,04,05" +_testsuite="01,02,04" + +_pwd=`pwd` + +_testclasses=".classes" +_testsrc="${_pwd}" +_lockFileName="JdpDoSomething.lck" + +_logname=".classes/output.txt" +_last_pid="" + + +_compile(){ + + if [ ! -e ${_testclasses} ] + then + mkdir -p ${_testclasses} + fi + + rm -f ${_testclasses}/*.class + + # Compile testcase + ${TESTJAVA}/bin/javac -d ${_testclasses} JdpUnitTest.java \ + JdpDoSomething.java \ + JdpClient.java + + + if [ ! -e ${_testclasses}/JdpDoSomething.class -o ! -e ${_testclasses}/JdpClient.class -o ! -e ${_testclasses}/JdpUnitTest.class ] + then + echo "ERROR: Can't compile" + exit -1 + fi +} + + +_app_start(){ + + testappname=$1 + shift + + ${TESTJAVA}/bin/java -server $* -cp ${_testclasses} ${testappname} >> ${_logname} 2>&1 & + _last_pid=$! + + npid=`_get_pid` + if [ "${npid}" = "" ] + then + echo "ERROR: Test app not started" + if [ "${_jtreg}" = "yes" ] + then + exit -1 + fi + fi +} + +_get_pid(){ + ${TESTJAVA}/bin/jps | sed -n "/Jdp/s/ .*//p" +} + +_app_stop(){ + rm ${_lockFileName} + +# wait until VM is actually shuts down + while true + do + npid=`_get_pid` + if [ "${npid}" = "" ] + then + break + fi + sleep 1 + done +} + +_testme(){ + ${TESTJAVA}/bin/java \ + -cp ${_testclasses} \ + $* \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + JdpClient + +} + + +_jcmd(){ + ${TESTJAVA}/bin/jcmd JdpDoSomething $* > /dev/null 2>/dev/null +} + + +_echo(){ + echo "$*" + echo "$*" >> ${_logname} +} + +# ============= TESTS ====================================== + +test_01(){ + + _echo "**** Test one ****" + + _app_start JdpUnitTest \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + -Dcom.sun.management.jdp.pause=5 + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_02(){ + + _echo "**** Test two ****" + + _app_start JdpDoSomething \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + -Dcom.sun.management.jdp.pause=5 \ + -Dcom.sun.management.jmxremote.port=4545 \ + -Dcom.sun.management.jmxremote.authenticate=false \ + -Dcom.sun.management.jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_03(){ + + _echo "**** Test three ****" + + _app_start JdpDoSomething + + _jcmd ManagementAgent.start\ + jdp.port=7095 \ + jdp.address=239.255.255.225 \ + jdp.pause=5 \ + jmxremote.port=4545 \ + jmxremote.authenticate=false \ + jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_04(){ + + _echo "**** Test four ****" + + _app_start JdpDoSomething \ + -Dcom.sun.management.jmxremote.autodiscovery=true \ + -Dcom.sun.management.jmxremote.port=4545 \ + -Dcom.sun.management.jmxremote.authenticate=false \ + -Dcom.sun.management.jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_05(){ + + _echo "**** Test five ****" + + _app_start JdpDoSomething + + _jcmd ManagementAgent.start\ + jmxremote.autodiscovery=true \ + jmxremote.port=4545 \ + jmxremote.authenticate=false \ + jmxremote.ssl=false + + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + + +# ============= MAIN ======================================= + +if [ "x${TESTJAVA}" = "x" ] +then + echo "TESTJAVA env have to be set" + exit +fi + +#------------------------------------------------------------------------------ +# reading parameters + +for parm in "$@" +do + case $parm in + --verbose) _verbose=yes ;; + --jtreg) _jtreg=yes ;; + --no-compile) _compile=no ;; + --testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;; + *) + echo "Undefined parameter $parm. Try --help for help" + exit + ;; + esac +done + +if [ ${_compile} = "yes" ] +then + _compile +fi + +if [ ${_jtreg} = "yes" ] +then + _testclasses=${TESTCLASSES} + _testsrc=${TESTSRC} + _logname="output.txt" +fi + +# Make sure _tesclasses is absolute path +tt=`echo ${_testclasses} | sed -e 's,/,,'` +if [ ${tt} = ${_testclasses} ] +then + _testclasses="${_pwd}/${_testclasses}" +fi + +_policyname="${_testclasses}/policy" + +rm -f ${_logname} +rm -f ${_policyname} + +if [ -e ${_testsrc}/policy.tpl ] +then + +cat ${_testsrc}/policy.tpl | \ + sed -e "s,@_TESTCLASSES@,${_testclasses},g" -e "s,@TESTJAVA@,${TESTJAVA},g" \ + > ${_policyname} + +fi + +# Local mode tests +for i in `echo ${_testsuite} | sed -e "s/,/ /g"` +do + test_${i} +done diff --git a/jdk/test/sun/management/jdp/JdpUnitTest.java b/jdk/test/sun/management/jdp/JdpUnitTest.java new file mode 100644 index 00000000000..fed4ae216c2 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpUnitTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.util.UUID; + +import sun.management.jdp.JdpController; +import sun.management.jdp.JdpPacket; +import sun.management.jdp.JdpJmxPacket; +import sun.management.jdp.JdpException; + +public class JdpUnitTest { + + /** + * This test tests that complete packet is build correctly + */ + public static void PacketBuilderTest() + throws IOException, JdpException { + + /* Complete packet test */ + { + JdpJmxPacket p1 = new JdpJmxPacket(UUID.randomUUID(), "fake://unit-test"); + p1.setMainClass("FakeUnitTest"); + p1.setInstanceName("Fake"); + byte[] b = p1.getPacketData(); + + JdpJmxPacket p2 = new JdpJmxPacket(b); + JdpDoSomething.printJdpPacket(p1); + JdpDoSomething.compaireJdpPacketEx(p1, p2); + } + + /*Missed field packet test*/ + { + JdpJmxPacket p1 = new JdpJmxPacket(UUID.randomUUID(), "fake://unit-test"); + p1.setMainClass("FakeUnitTest"); + p1.setInstanceName(null); + byte[] b = p1.getPacketData(); + + JdpJmxPacket p2 = new JdpJmxPacket(b); + JdpDoSomething.printJdpPacket(p1); + JdpDoSomething.compaireJdpPacketEx(p1, p2); + } + + System.out.println("OK: Test passed"); + + } + + public static void startFakeDiscoveryService() + throws IOException, JdpException { + + String discoveryPort = System.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = System.getProperty("com.sun.management.jdp.address"); + InetAddress address = InetAddress.getByName(discoveryAddress); + int port = Integer.parseInt(discoveryPort); + JdpController.startDiscoveryService(address, port, "FakeDiscovery", "fake://unit-test"); + } + + public static void main(String[] args) { + try { + PacketBuilderTest(); + startFakeDiscoveryService(); + JdpDoSomething.doSomething(); + + } catch (Throwable e) { + e.printStackTrace(); + System.out.println("Test failed. unexpected error " + e); + } + } +} diff --git a/jdk/test/sun/net/www/EncDec.doc b/jdk/test/sun/net/ftp/EncDec.doc similarity index 100% rename from jdk/test/sun/net/www/EncDec.doc rename to jdk/test/sun/net/ftp/EncDec.doc diff --git a/jdk/test/sun/net/www/MarkResetTest.java b/jdk/test/sun/net/ftp/MarkResetTest.java similarity index 100% rename from jdk/test/sun/net/www/MarkResetTest.java rename to jdk/test/sun/net/ftp/MarkResetTest.java diff --git a/jdk/test/sun/net/www/MarkResetTest.sh b/jdk/test/sun/net/ftp/MarkResetTest.sh similarity index 100% rename from jdk/test/sun/net/www/MarkResetTest.sh rename to jdk/test/sun/net/ftp/MarkResetTest.sh diff --git a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java index 18c2e1f0840..5d13a58d8cb 100644 --- a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java +++ b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java @@ -161,8 +161,18 @@ public class ProxyTest { } } + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } + public static void main(String[] args) throws Exception { - ProxyTest test = new ProxyTest(); + if (hasFtp()) + new ProxyTest(); } public ProxyTest() throws Exception { diff --git a/jdk/test/sun/security/pkcs12/StorePasswordTest.java b/jdk/test/sun/security/pkcs12/StorePasswordTest.java index fc2f77c51c1..821b1759a2c 100644 --- a/jdk/test/sun/security/pkcs12/StorePasswordTest.java +++ b/jdk/test/sun/security/pkcs12/StorePasswordTest.java @@ -47,40 +47,49 @@ public class StorePasswordTest { new File(KEYSTORE).delete(); - try { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); - - // Set entry - keystore.setEntry(ALIAS, - new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD)), - new KeyStore.PasswordProtection(PASSWORD)); + // Set entry + Set attrs = new HashSet<>(); + attrs.add(new PKCS12Attribute("1.3.5.7.9", "printable1")); + attrs.add(new PKCS12Attribute("2.4.6.8.10", "1F:2F:3F:4F:5F")); + int originalAttrCount = attrs.size() + 2; + keystore.setEntry(ALIAS, + new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD), attrs), + new KeyStore.PasswordProtection(PASSWORD)); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); - KeyStore.Entry entry = keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry: " + entry); + } - SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD); - SecretKeyFactory factory = - SecretKeyFactory.getInstance(key.getAlgorithm()); - PBEKeySpec keySpec = - (PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class); - char[] pwd = keySpec.getPassword(); - System.out.println("Recovered credential: " + new String(pwd)); + KeyStore.Entry entry = keystore.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + int attrCount = entry.getAttributes().size(); + System.out.println("Retrieved entry with " + attrCount + " attrs: " + + entry); + if (attrCount != originalAttrCount) { + throw new Exception("Failed to recover all the entry attributes"); + } - if (!Arrays.equals(USER_PASSWORD.toCharArray(), pwd)) { - throw new Exception("Failed to recover the stored password"); - } - } finally { - new File(KEYSTORE).delete(); + SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD); + SecretKeyFactory factory = + SecretKeyFactory.getInstance(key.getAlgorithm()); + PBEKeySpec keySpec = + (PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class); + char[] pwd = keySpec.getPassword(); + System.out.println("Recovered credential: " + new String(pwd)); + + if (!Arrays.equals(USER_PASSWORD.toCharArray(), pwd)) { + throw new Exception("Failed to recover the stored password"); } } diff --git a/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java b/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java index f002ef7506a..84c28899126 100644 --- a/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java +++ b/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java @@ -53,35 +53,34 @@ public class StoreSecretKeyTest { new File(KEYSTORE).delete(); - try { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); - - // Set entry - keystore.setEntry(ALIAS, - new KeyStore.SecretKeyEntry(generateSecretKey("AES", 128)), - new KeyStore.PasswordProtection(PASSWORD)); + // Set entry + keystore.setEntry(ALIAS, + new KeyStore.SecretKeyEntry(generateSecretKey("AES", 128)), + new KeyStore.PasswordProtection(PASSWORD)); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); - KeyStore.Entry entry = keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry: " + entry); + } - if (entry instanceof KeyStore.SecretKeyEntry) { - System.out.println("Retrieved secret key entry: " + - entry); - } else { - throw new Exception("Not a secret key entry"); - } - } finally { - new File(KEYSTORE).delete(); + KeyStore.Entry entry = keystore.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + System.out.println("Retrieved entry: " + entry); + + if (entry instanceof KeyStore.SecretKeyEntry) { + System.out.println("Retrieved secret key entry: " + entry); + } else { + throw new Exception("Not a secret key entry"); } } diff --git a/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java b/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java index a1481749d7e..0cbca31e2d1 100644 --- a/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java +++ b/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java @@ -49,59 +49,57 @@ public class StoreTrustedCertTest { new File(KEYSTORE).delete(); - try { - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - Certificate cert = loadCertificate(CERT); - Set attributes = new HashSet<>(); - attributes.add(new PKCS12Attribute("1.3.5.7.9", "that's odd")); - attributes.add(new PKCS12Attribute("2.4.6.8.10", "that's even")); + Certificate cert = loadCertificate(CERT); + Set attributes = new HashSet<>(); + attributes.add(new PKCS12Attribute("1.3.5.7.9", "that's odd")); + attributes.add(new PKCS12Attribute("2.4.6.8.10", "that's even")); - // Set trusted certificate entry - keystore.setEntry(ALIAS, - new KeyStore.TrustedCertificateEntry(cert), null); + // Set trusted certificate entry + keystore.setEntry(ALIAS, + new KeyStore.TrustedCertificateEntry(cert), null); - // Set trusted certificate entry with attributes - keystore.setEntry(ALIAS2, - new KeyStore.TrustedCertificateEntry(cert, attributes), null); + // Set trusted certificate entry with attributes + keystore.setEntry(ALIAS2, + new KeyStore.TrustedCertificateEntry(cert, attributes), null); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); + } - KeyStore.Entry entry = keystore.getEntry(ALIAS, null); - if (entry instanceof KeyStore.TrustedCertificateEntry) { - System.out.println("Retrieved trusted certificate entry: " + - entry); + KeyStore.Entry entry = keystore.getEntry(ALIAS, null); + if (entry instanceof KeyStore.TrustedCertificateEntry) { + System.out.println("Retrieved trusted certificate entry: " + entry); + } else { + throw new Exception("Not a trusted certificate entry"); + } + System.out.println(); + + entry = keystore.getEntry(ALIAS2, null); + if (entry instanceof KeyStore.TrustedCertificateEntry) { + KeyStore.TrustedCertificateEntry trustedEntry = + (KeyStore.TrustedCertificateEntry) entry; + Set entryAttributes = + trustedEntry.getAttributes(); + + if (entryAttributes.containsAll(attributes)) { + System.out.println("Retrieved trusted certificate entry " + + "with attributes: " + entry); } else { - throw new Exception("Not a trusted certificate entry"); + throw new Exception("Failed to retrieve entry attributes"); } - System.out.println(); - - entry = keystore.getEntry(ALIAS2, null); - if (entry instanceof KeyStore.TrustedCertificateEntry) { - KeyStore.TrustedCertificateEntry trustedEntry = - (KeyStore.TrustedCertificateEntry) entry; - Set entryAttributes = - trustedEntry.getAttributes(); - - if (entryAttributes.containsAll(attributes)) { - System.out.println("Retrieved trusted certificate entry " + - "with attributes: " + entry); - } else { - throw new Exception("Failed to retrieve entry attributes"); - } - } else { - throw new Exception("Not a trusted certificate entry"); - } - - } finally { - new File(KEYSTORE).delete(); + } else { + throw new Exception("Not a trusted certificate entry"); } } diff --git a/jdk/test/sun/security/util/Oid/S11N.java b/jdk/test/sun/security/util/Oid/S11N.java new file mode 100644 index 00000000000..a5595d10112 --- /dev/null +++ b/jdk/test/sun/security/util/Oid/S11N.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 4811968 6908628 8006564 + * @run main S11N check + * @summary Serialization compatibility with old versions (and fixes) + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.Map; +import sun.misc.BASE64Encoder; +import sun.security.util.ObjectIdentifier; + +public class S11N { + static String[] SMALL= { + "0.0", + "1.1", + "2.2", + "1.2.3456", + "1.2.2147483647.4", + "1.2.268435456.4", + }; + + static String[] HUGE = { + "2.16.764.1.3101555394.1.0.100.2.1", + "1.2.2147483648.4", + "2.3.4444444444444444444444", + "1.2.8888888888888888.33333333333333333.44444444444444", + }; + + // Do not use j.u.Base64, the test needs to run in jdk6 + static BASE64Encoder encoder = new BASE64Encoder() { + @Override + protected int bytesPerLine() { + return 48; + } + }; + + public static void main(String[] args) throws Exception { + if (args[0].equals("check")) { + int version = Integer.valueOf(System.getProperty("java.version") + .split("\\.")[1]); + System.out.println("version is " + version); + if (version >= 7) { + for (String oid: SMALL) { + // 7 -> 7 + check(out(oid), oid); + // 6 -> 7 + check(out6(oid), oid); + } + for (String oid: HUGE) { + // 7 -> 7 + check(out(oid), oid); + } + } else { + for (String oid: SMALL) { + // 6 -> 6 + check(out(oid), oid); + // 7 -> 6 + check(out7(oid), oid); + } + for (String oid: HUGE) { + // 7 -> 6 fails for HUGE oids + boolean ok = false; + try { + check(out7(oid), oid); + ok = true; + } catch (Exception e) { + System.out.println(e); + } + if (ok) { + throw new Exception(); + } + } + } + } else { + // Generates the JDK6 serialized string inside this test, call + // $JDK7/bin/java S11N dump7 + // $JDK6/bin/java S11N dump6 + // and paste the output at the end of this test. + dump(args[0], SMALL); + // For jdk6, the following line will throw an exception, ignore it + dump(args[0], HUGE); + } + } + + // Gets the serialized form for jdk6 + private static byte[] out6(String oid) throws Exception { + return new sun.misc.BASE64Decoder().decodeBuffer(dump6.get(oid)); + } + + // Gets the serialized form for jdk7 + private static byte[] out7(String oid) throws Exception { + return new sun.misc.BASE64Decoder().decodeBuffer(dump7.get(oid)); + } + + // Gets the serialized form for this java + private static byte[] out(String oid) throws Exception { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + new ObjectOutputStream(bout).writeObject(new ObjectIdentifier(oid)); + return bout.toByteArray(); + } + + // Makes sure serialized form can be deserialized + private static void check(byte[] in, String oid) throws Exception { + ObjectIdentifier o = (ObjectIdentifier) ( + new ObjectInputStream(new ByteArrayInputStream(in)).readObject()); + if (!o.toString().equals(oid)) { + throw new Exception("Read Fail " + o + ", not " + oid); + } + } + + // dump serialized form to java code style text + private static void dump(String title, String[] oids) throws Exception { + for (String oid: oids) { + String[] base64 = encoder.encodeBuffer(out(oid)).split("\n"); + System.out.println(" " + title + ".put(\"" + oid + "\","); + for (int i = 0; i dump7 = new HashMap(); + private static Map dump6 = new HashMap(); + + static { + ////////////// PASTE BEGIN ////////////// + dump7.put("0.0", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAAAAAAB1cgACW0Ks8xf4BghU4AIAAHhwAAAAAQB4"); + dump7.put("1.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAQAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAAASl4"); + dump7.put("2.2", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAgAAAAJ1cgACW0Ks8xf4BghU4AIAAHhwAAAAAVJ4"); + dump7.put("1.2.3456", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAA3VyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAADAAAAAQAAAAIAAA2AdXIAAltCrPMX+AYIVOACAAB4cAAAAAMqmwB4"); + dump7.put("1.2.2147483647.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAAEAAAAAQAAAAJ/////AAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKof///9/" + + "BHg="); + dump7.put("1.2.268435456.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAAEAAAAAQAAAAIQAAAAAAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKoGAgIAA" + + "BHg="); + dump7.put("2.16.764.1.3101555394.1.0.100.2.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADmCFfAGLxvf1QgEAZAIB" + + "eA=="); + dump7.put("1.2.2147483648.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAByqIgICAAAR4"); + dump7.put("2.3.4444444444444444444444", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADFOD4e+HpNG968eOHHg="); + dump7.put("1.2.8888888888888888.33333333333333333.44444444444444", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAGCqP5Yzbxa6cOLubj9ek" + + "japVio3AusuOHHg="); + + dump6.put("0.0", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAAAAAAA"); + dump6.put("1.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAEAAAAB"); + dump6.put("2.2", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAIAAAAC"); + dump6.put("1.2.3456", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAN1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAwAAAAEAAAACAAANgA=="); + dump6.put("1.2.2147483647.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" + + "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACf////wAAAAQ="); + dump6.put("1.2.268435456.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" + + "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACEAAAAAAAAAQ="); + ////////////// PASTE END ////////////// + } +} diff --git a/jdk/test/sun/security/util/Oid/S11N.sh b/jdk/test/sun/security/util/Oid/S11N.sh deleted file mode 100644 index a19af17be5f..00000000000 --- a/jdk/test/sun/security/util/Oid/S11N.sh +++ /dev/null @@ -1,188 +0,0 @@ -# -# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# @test -# @bug 4811968 6908628 -# @summary Serialization compatibility with old versions (and fix) -# @author Weijun Wang -# -# set a few environment variables so that the shell-script can run stand-alone -# in the source directory - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi -if [ "${TESTCLASSES}" = "" ] ; then - TESTCLASSES="." -fi -if [ "${TESTJAVA}" = "" ] ; then - echo "TESTJAVA not set. Test cannot execute." - echo "FAILED!!!" - exit 1 -fi -if [ "${COMPILEJAVA}" = "" ]; then - COMPILEJAVA="${TESTJAVA}" -fi - -# set platform-dependent variables -PF="" - -OS=`uname -s` -case "$OS" in - SunOS ) - FS="/" - ARCH=`isainfo` - case "$ARCH" in - sparc* ) - PF="solaris-sparc" - ;; - i[3-6]86 ) - PF="solaris-i586" - ;; - amd64* ) - PF="solaris-amd64" - ;; - * ) - echo "Unsupported System: Solaris ${ARCH}" - exit 0; - ;; - esac - ;; - Linux ) - ARCH=`uname -m` - FS="/" - case "$ARCH" in - i[3-6]86 ) - PF="linux-i586" - ;; - amd64* | x86_64 ) - PF="linux-amd64" - ;; - * ) - echo "Unsupported System: Linux ${ARCH}" - exit 0; - ;; - esac - ;; - Windows* ) - FS="\\" - PF="windows-i586" - - # 'uname -m' does not give us enough information - - # should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk), - # but JTREG does not pass this env variable when executing a shell script. - # - # execute test program - rely on it to exit if platform unsupported - - ;; - * ) - echo "Unsupported System: ${OS}" - exit 0; - ;; -esac - -echo "===================================================" -echo "Try to set ALT_JAVA_RE_JDK if you see timeout error" -echo "===================================================" - -# the test code - -${COMPILEJAVA}${FS}bin${FS}javac -target 1.4 -source 1.4 \ - -d . ${TESTSRC}${FS}SerialTest.java || exit 10 - -# You can set ALT_JAVA_RE_JDK to another location that contains the -# binaries for older JDK releases. You can set it to a non-existent -# directory to skip the interop tests between different versions. - -if [ "$ALT_JAVA_RE_JDK" = "" ]; then - JAVA_RE_JDK=/java/re/j2se -else - JAVA_RE_JDK=$ALT_JAVA_RE_JDK -fi - -OLDJAVA=" - $JAVA_RE_JDK/1.6.0/latest/binaries/${PF} - $JAVA_RE_JDK/1.5.0/latest/binaries/${PF} - $JAVA_RE_JDK/1.4.2/latest/binaries/${PF} -" - -SMALL=" - 0.0 - 1.1 - 2.2 - 1.2.3456 - 1.2.2147483647.4 - 1.2.268435456.4 -" - -HUGE=" - 2.16.764.1.3101555394.1.0.100.2.1 - 1.2.2147483648.4 - 2.3.4444444444444444444444 - 1.2.888888888888888888.111111111111111.2222222222222.33333333333333333.44444444444444 -" - -for oid in ${SMALL}; do - echo ${oid} - # new -> - ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2 - for oldj in ${OLDJAVA}; do - if [ -d ${oldj} ]; then - echo ${oldj} - # -> old - ${oldj}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 3 - # old -> - ${oldj}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial.old || exit 4 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial.old || exit 5 - fi - done -done - -for oid in ${HUGE}; do - echo ${oid} - # new -> - ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2 - for oldj in ${OLDJAVA}; do - if [ -d ${oldj} ]; then - echo ${oldj} - # -> old - ${oldj}${FS}bin${FS}java SerialTest badin < tmp.oid.serial || exit 3 - fi - done -done - -rm -f tmp.oid.serial -rm -f tmp.oid.serial.old -rm -f SerialTest.class - -for oldj in ${OLDJAVA}; do - if [ ! -d ${oldj} ]; then - echo WARNING: ${oldj} is missing. Test incomplete! > /dev/stderr - fi -done - -exit 0 diff --git a/jdk/test/sun/security/util/Oid/SerialTest.java b/jdk/test/sun/security/util/Oid/SerialTest.java deleted file mode 100644 index ba127441cad..00000000000 --- a/jdk/test/sun/security/util/Oid/SerialTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * read S11.sh - */ -import java.io.*; -import sun.security.util.*; - -/** - * Test OID serialization between versions - * - * java SerialTest out oid // write a OID into System.out - * java SerialTest in oid // read from System.in and compare it with oid - * java SerialTest badin // make sure *cannot* read from System.in - */ -class SerialTest { - public static void main(String[] args) throws Exception { - if (args[0].equals("out")) - out(args[1]); - else if (args[0].equals("in")) - in(args[1]); - else - badin(); - } - - static void in(String oid) throws Exception { - ObjectIdentifier o = (ObjectIdentifier) (new ObjectInputStream(System.in).readObject()); - if (!o.toString().equals(oid)) - throw new Exception("Read Fail " + o + ", not " + oid); - } - - static void badin() throws Exception { - boolean pass = true; - try { - new ObjectInputStream(System.in).readObject(); - } catch (Exception e) { - pass = false; - } - if (pass) throw new Exception("Should fail but not"); - } - - static void out(String oid) throws Exception { - new ObjectOutputStream(System.out).writeObject(new ObjectIdentifier(oid)); - } -} diff --git a/jdk/test/tools/launcher/Arrrghs.java b/jdk/test/tools/launcher/Arrrghs.java index 9bf9f21b465..cf0dfbf7410 100644 --- a/jdk/test/tools/launcher/Arrrghs.java +++ b/jdk/test/tools/launcher/Arrrghs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -309,6 +309,7 @@ public class Arrrghs extends TestHelper { checkArgumentParsing("../../*", "../../*"); checkArgumentParsing("..\\..\\", "..\\..\\"); checkArgumentParsing("../../", "../../"); + checkArgumentParsing("a b\\ c", "a", "b\\", "c"); } private void initEmptyDir(File emptyDir) throws IOException { diff --git a/jdk/test/tools/launcher/VersionCheck.java b/jdk/test/tools/launcher/VersionCheck.java index c30ef424011..11f65cb2e9a 100644 --- a/jdk/test/tools/launcher/VersionCheck.java +++ b/jdk/test/tools/launcher/VersionCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -42,6 +42,7 @@ public class VersionCheck extends TestHelper { // tools that do not accept -J-option static final String[] BLACKLIST_JOPTION = { "controlpanel", + "jabswitch", "java-rmi", "java-rmi.cgi", "java", diff --git a/jdk/test/tools/pack200/InstructionTests.java b/jdk/test/tools/pack200/InstructionTests.java new file mode 100644 index 00000000000..ce92c0ed558 --- /dev/null +++ b/jdk/test/tools/pack200/InstructionTests.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 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.File; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import static java.nio.file.StandardOpenOption.*; +import java.util.regex.Pattern; + +/* + * @test + * @bug 8003549 + * @summary tests class files instruction formats introduced in JSR-335 + * @compile -XDignore.symbol.file Utils.java InstructionTests.java + * @run main InstructionTests + * @author ksrini + */ +public class InstructionTests { + public static void main(String... args) throws Exception { + testInvokeOpCodes(); + } + /* + * the following should produce invokestatic and invokespecial + * on InterfaceMethodRefs vs. MethodRefs, packer/unpacker should work + */ + static void testInvokeOpCodes() throws Exception { + List scratch = new ArrayList<>(); + final String fname = "A"; + String javaFileName = fname + Utils.JAVA_FILE_EXT; + scratch.add("interface IntIterator {"); + scratch.add(" default void forEach(){}"); + scratch.add(" static void next() {}"); + scratch.add("}"); + scratch.add("class A implements IntIterator {"); + scratch.add("public void forEach(Object o){"); + scratch.add("IntIterator.super.forEach();"); + scratch.add("IntIterator.next();"); + scratch.add("}"); + scratch.add("}"); + File cwd = new File("."); + File javaFile = new File(cwd, javaFileName); + Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(), + CREATE, TRUNCATE_EXISTING); + + // make sure we have -g so that we compare LVT and LNT entries + Utils.compiler("-g", javaFile.getName()); + + // jar the file up + File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); + Utils.jar("cvf", testjarFile.getName(), "."); + + // pack using --repack + File outjarFile = new File(cwd, "out" + Utils.JAR_FILE_EXT); + scratch.clear(); + scratch.add(Utils.getPack200Cmd()); + scratch.add("-J-ea"); + scratch.add("-J-esa"); + scratch.add("--repack"); + scratch.add(outjarFile.getName()); + scratch.add(testjarFile.getName()); + List output = Utils.runExec(scratch); + // TODO remove this when we get bc escapes working correctly + // this test anyhow would fail at that time + findString("WARNING: Passing.*" + fname + Utils.CLASS_FILE_EXT, + output); + + Utils.doCompareVerify(testjarFile, outjarFile); + } + + static boolean findString(String str, List list) { + Pattern p = Pattern.compile(str); + for (String x : list) { + if (p.matcher(x).matches()) + return true; + } + throw new RuntimeException("Error: " + str + " not found in output"); + } +} diff --git a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java index 177849872a9..db7d0465777 100644 --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java +++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java @@ -57,8 +57,10 @@ import com.sun.tools.classfile.MethodParameters_attribute; import com.sun.tools.classfile.Opcode; import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; import com.sun.tools.classfile.Signature_attribute; import com.sun.tools.classfile.SourceDebugExtension_attribute; import com.sun.tools.classfile.SourceFile_attribute; @@ -1214,6 +1216,21 @@ class AttributeVisitor implements Attribute.Visitor { p.add(e); return null; } + + /* + * TODO + * add these two for now to keep the compiler happy, we will implement + * these along with the JSR-308 changes. + */ + @Override + public Element visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute rvta, Element p) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Element visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute rita, Element p) { + throw new UnsupportedOperationException("Not supported yet."); + } } class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor { diff --git a/langtools/.hgtags b/langtools/.hgtags index cd611eef514..788268b7d8a 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -195,3 +195,6 @@ d7360bf35ee1f40ff78c2e83a22b5446ee464346 jdk8-b69 467e4d9281bcf119eaec42af1423c96bd401871c jdk8-b71 6f0986ed9b7e11d6eb06618f27e20b18f19fb797 jdk8-b72 8d0baee36c7184d55c80354b45704c37d6b7ac79 jdk8-b73 +56c97aff46bb577b8668874154c24115a7e8a3e8 jdk8-b74 +c2e11e2ec4a3682513e566849e5562f31ded8c65 jdk8-b75 +e81839b3233792415daaab051698edc6067f1a16 jdk8-b76 diff --git a/langtools/make/Makefile-classic b/langtools/make/Makefile-classic index f0693b7216b..c253ee8949b 100644 --- a/langtools/make/Makefile-classic +++ b/langtools/make/Makefile-classic @@ -241,6 +241,7 @@ JAVAC_DIRS = \ javax/annotation/processing \ javax/lang/model \ javax/tools \ + jdk/ \ com/sun/source \ com/sun/tools/javac diff --git a/langtools/make/build.properties b/langtools/make/build.properties index 3470a69d868..7fd5ffcb371 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -29,18 +29,18 @@ # Override this path as needed, either on the command line or in # one of the standard user build.properties files (see build.xml) -# boot.java.home = /opt/jdk/1.6.0 +# boot.java.home = /opt/jdk/1.7.0 boot.java = ${boot.java.home}/bin/java boot.javac = ${boot.java.home}/bin/javac -boot.javac.source = 6 -boot.javac.target = 6 +boot.javac.source = 7 +boot.javac.target = 7 # This is the JDK used to run the product version of the tools, # for example, for testing. If you're building a complete JDK, specify that. # Override this path as needed, either on the command line or in # one of the standard user build.properties files (see build.xml) -# target.java.home = /opt/jdk/1.7.0 +# target.java.home = /opt/jdk/1.8.0 target.java = ${target.java.home}/bin/java # Version info -- override as needed @@ -116,6 +116,7 @@ javac.includes = \ javax/annotation/processing/ \ javax/lang/model/ \ javax/tools/ \ + jdk/ \ com/sun/source/ \ com/sun/tools/javac/ \ com/sun/tools/doclint/ @@ -161,6 +162,14 @@ javap.tests = \ # +sjavac.includes = \ + com/sun/tools/sjavac/ + +sjavac.tests = \ + tools/sjavac + +# + # The following files require the latest JDK to be available. # The API can be provided by using a suitable boot.java.home # or by setting import.jdk diff --git a/langtools/make/build.xml b/langtools/make/build.xml index be1c357852c..9292ee3f392 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -241,15 +241,15 @@ - + @@ -656,6 +656,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + * @@ -1486,6 +1665,7 @@ public class Type implements PrimitiveType { R visitForAll(ForAll t, S s); R visitUndetVar(UndetVar t, S s); R visitErrorType(ErrorType t, S s); + R visitAnnotatedType(AnnotatedType t, S s); R visitType(Type t, S s); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java index c3fba38ff85..32a6ffdc8f4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.tools.javac.code; +import java.util.Iterator; + import com.sun.tools.javac.util.*; /** A type annotation position. @@ -34,12 +36,92 @@ import com.sun.tools.javac.util.*; * This code and its internal interfaces are subject to change or * deletion without notice. */ +// Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position public class TypeAnnotationPosition { + public enum TypePathEntryKind { + ARRAY(0), + INNER_TYPE(1), + WILDCARD(2), + TYPE_ARGUMENT(3); + + public final int tag; + + private TypePathEntryKind(int tag) { + this.tag = tag; + } + } + + public static class TypePathEntry { + /** The fixed number of bytes per TypePathEntry. */ + public static final int bytesPerEntry = 2; + + public final TypePathEntryKind tag; + public final int arg; + + public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY); + public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE); + public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD); + + private TypePathEntry(TypePathEntryKind tag) { + Assert.check(tag == TypePathEntryKind.ARRAY || + tag == TypePathEntryKind.INNER_TYPE || + tag == TypePathEntryKind.WILDCARD, + "Invalid TypePathEntryKind: " + tag); + this.tag = tag; + this.arg = 0; + } + + public TypePathEntry(TypePathEntryKind tag, int arg) { + Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT, + "Invalid TypePathEntryKind: " + tag); + this.tag = tag; + this.arg = arg; + } + + public static TypePathEntry fromBinary(int tag, int arg) { + Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag, + "Invalid TypePathEntry tag/arg: " + tag + "/" + arg); + switch (tag) { + case 0: + return ARRAY; + case 1: + return INNER_TYPE; + case 2: + return WILDCARD; + case 3: + return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg); + default: + Assert.error("Invalid TypePathEntryKind tag: " + tag); + return null; + } + } + + @Override + public String toString() { + return tag.toString() + + (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : ""); + } + + @Override + public boolean equals(Object other) { + if (! (other instanceof TypePathEntry)) { + return false; + } + TypePathEntry tpe = (TypePathEntry) other; + return this.tag == tpe.tag && this.arg == tpe.arg; + } + + @Override + public int hashCode() { + return this.tag.hashCode() * 17 + this.arg; + } + } + public TargetType type = TargetType.UNKNOWN; // For generic/array types. - public List location = List.nil(); + public List location = List.nil(); // Tree position. public int pos = -1; @@ -59,11 +141,13 @@ public class TypeAnnotationPosition { // For type parameter and method parameter public int parameter_index = Integer.MIN_VALUE; - // For class extends, implements, and throws classes + // For class extends, implements, and throws clauses public int type_index = Integer.MIN_VALUE; - // For wildcards - public TypeAnnotationPosition wildcard_position = null; + // For exception parameters, index into exception table + public int exception_index = Integer.MIN_VALUE; + + public TypeAnnotationPosition() {} @Override public String toString() { @@ -72,27 +156,27 @@ public class TypeAnnotationPosition { sb.append(type); switch (type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation + // type cast + case CAST: + // instanceof case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression + // new expression case NEW: - case NEW_GENERIC_OR_ARRAY: - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: sb.append(", offset = "); sb.append(offset); break; - // local variable + // local variable case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: + // resource variable + case RESOURCE_VARIABLE: + if (lvarOffset == null) { + sb.append(", lvarOffset is null!"); + break; + } sb.append(", {"); for (int i = 0; i < lvarOffset.length; ++i) { if (i != 0) sb.append("; "); - sb.append(", start_pc = "); + sb.append("start_pc = "); sb.append(lvarOffset[i]); sb.append(", length = "); sb.append(lvarLength[i]); @@ -101,73 +185,72 @@ public class TypeAnnotationPosition { } sb.append("}"); break; - // method receiver + // method receiver case METHOD_RECEIVER: // Do nothing break; - // type parameters + // type parameter case CLASS_TYPE_PARAMETER: case METHOD_TYPE_PARAMETER: sb.append(", param_index = "); sb.append(parameter_index); break; - // type parameters bound + // type parameter bound case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: sb.append(", param_index = "); sb.append(parameter_index); sb.append(", bound_index = "); sb.append(bound_index); break; - // wildcard - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - sb.append(", wild_card = "); - sb.append(wildcard_position); - break; - // Class extends and implements clauses + // class extends or implements clause case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: sb.append(", type_index = "); sb.append(type_index); break; - // throws + // throws case THROWS: sb.append(", type_index = "); sb.append(type_index); break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - sb.append(", offset = "); - sb.append(offset); + // exception parameter + case EXCEPTION_PARAMETER: + sb.append(", exception_index = "); + sb.append(exception_index); break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: + // method parameter + case METHOD_FORMAL_PARAMETER: sb.append(", param_index = "); sb.append(parameter_index); break; - // method type argument: wasn't specified - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: + // method/constructor/reference type argument + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: sb.append(", offset = "); sb.append(offset); sb.append(", type_index = "); sb.append(type_index); break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: + // We don't need to worry about these + case METHOD_RETURN: + case FIELD: + break; + // lambda formal parameter + case LAMBDA_FORMAL_PARAMETER: + // TODO: also needs an offset? + sb.append(", param_index = "); + sb.append(parameter_index); break; case UNKNOWN: + sb.append(", position UNKNOWN!"); break; default: - // throw new AssertionError("unknown type: " + type); + Assert.error("Unknown target type: " + type); } // Append location data for generics/arrays. - if (type.hasLocation()) { + if (!location.isEmpty()) { sb.append(", location = ("); sb.append(location); sb.append(")"); @@ -186,10 +269,33 @@ public class TypeAnnotationPosition { * @return true if the target has not been optimized away */ public boolean emitToClassfile() { - if (type == TargetType.WILDCARD_BOUND - || type == TargetType.WILDCARD_BOUND_GENERIC_OR_ARRAY) - return wildcard_position.isValidOffset; - else - return !type.isLocal() || isValidOffset; + return !type.isLocal() || isValidOffset; + } + + /** + * Decode the binary representation for a type path and set + * the {@code location} field. + * + * @param list The bytecode representation of the type path. + */ + public static List getTypePathFromBinary(java.util.List list) { + ListBuffer loc = ListBuffer.lb(); + Iterator iter = list.iterator(); + while (iter.hasNext()) { + Integer fst = iter.next(); + Assert.check(iter.hasNext(), "Could not decode type path: " + list); + Integer snd = iter.next(); + loc = loc.append(TypePathEntry.fromBinary(fst, snd)); + } + return loc.toList(); + } + + public static List getBinaryFromTypePath(java.util.List locs) { + ListBuffer loc = ListBuffer.lb(); + for (TypePathEntry tpe : locs) { + loc = loc.append(tpe.tag.tag); + loc = loc.append(tpe.arg); + } + return loc.toList(); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java new file mode 100644 index 00000000000..b438b2f1e93 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java @@ -0,0 +1,1037 @@ +/* + * Copyright (c) 2009, 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 com.sun.tools.javac.code; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.type.TypeKind; + +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Attribute.TypeCompound; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Type.AnnotatedType; +import com.sun.tools.javac.code.Type.ArrayType; +import com.sun.tools.javac.code.Type.CapturedType; +import com.sun.tools.javac.code.Type.ClassType; +import com.sun.tools.javac.code.Type.ErrorType; +import com.sun.tools.javac.code.Type.ForAll; +import com.sun.tools.javac.code.Type.MethodType; +import com.sun.tools.javac.code.Type.PackageType; +import com.sun.tools.javac.code.Type.TypeVar; +import com.sun.tools.javac.code.Type.UndetVar; +import com.sun.tools.javac.code.Type.Visitor; +import com.sun.tools.javac.code.Type.WildcardType; +import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; +import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind; +import com.sun.tools.javac.code.TypeTag; +import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.comp.Annotate.Annotator; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCTypeApply; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Names; + +/** + * Contains operations specific to processing type annotations. + * This class has two functions: + * separate declaration from type annotations and insert the type + * annotations to their types; + * and determine the TypeAnnotationPositions for all type annotations. + */ +public class TypeAnnotations { + // Class cannot be instantiated. + private TypeAnnotations() {} + + /** + * Separate type annotations from declaration annotations and + * determine the correct positions for type annotations. + * This version only visits types in signatures and should be + * called from MemberEnter. + * The method returns the Annotator object that should be added + * to the correct Annotate queue for later processing. + */ + public static Annotator organizeTypeAnnotationsSignatures(final Symtab syms, final Names names, + final Log log, final JCClassDecl tree) { + return new Annotator() { + @Override + public void enterAnnotation() { + new TypeAnnotationPositions(syms, names, log, true).scan(tree); + } + }; + } + + /** + * This version only visits types in bodies, that is, field initializers, + * top-level blocks, and method bodies, and should be called from Attr. + */ + public static void organizeTypeAnnotationsBodies(Symtab syms, Names names, Log log, JCClassDecl tree) { + new TypeAnnotationPositions(syms, names, log, false).scan(tree); + } + + private static class TypeAnnotationPositions extends TreeScanner { + + private enum AnnotationType { DECLARATION, TYPE, BOTH }; + + private final Symtab syms; + private final Names names; + private final Log log; + private final boolean sigOnly; + + private TypeAnnotationPositions(Symtab syms, Names names, Log log, boolean sigOnly) { + this.syms = syms; + this.names = names; + this.log = log; + this.sigOnly = sigOnly; + } + + /* + * When traversing the AST we keep the "frames" of visited + * trees in order to determine the position of annotations. + */ + private ListBuffer frames = ListBuffer.lb(); + + protected void push(JCTree t) { frames = frames.prepend(t); } + protected JCTree pop() { return frames.next(); } + // could this be frames.elems.tail.head? + private JCTree peek2() { return frames.toList().tail.head; } + + @Override + public void scan(JCTree tree) { + push(tree); + super.scan(tree); + pop(); + } + + /** + * Separates type annotations from declaration annotations. + * This step is needed because in certain locations (where declaration + * and type annotations can be mixed, e.g. the type of a field) + * we never build an JCAnnotatedType. This step finds these + * annotations and marks them as if they were part of the type. + */ + private void separateAnnotationsKinds(JCTree typetree, Type type, Symbol sym, + TypeAnnotationPosition pos) { + /* + System.out.printf("separateAnnotationsKinds(typetree: %s, type: %s, symbol: %s, pos: %s%n", + typetree, type, sym, pos); + */ + List annotations = sym.getRawAttributes(); + ListBuffer declAnnos = new ListBuffer(); + ListBuffer typeAnnos = new ListBuffer(); + + for (Attribute.Compound a : annotations) { + switch (annotationType(a, sym)) { + case DECLARATION: + declAnnos.append(a); + break; + case BOTH: { + declAnnos.append(a); + Attribute.TypeCompound ta = toTypeCompound(a, pos); + typeAnnos.append(ta); + break; + } + case TYPE: { + Attribute.TypeCompound ta = toTypeCompound(a, pos); + typeAnnos.append(ta); + break; + } + } + } + + sym.annotations.reset(); + sym.annotations.setDeclarationAttributes(declAnnos.toList()); + + List typeAnnotations = typeAnnos.toList(); + + if (type == null) { + // When type is null, put the type annotations to the symbol. + // This is used for constructor return annotations, for which + // no appropriate type exists. + sym.annotations.appendUniqueTypes(typeAnnotations); + return; + } + + // type is non-null and annotations are added to that type + type = typeWithAnnotations(typetree, type, typeAnnotations, log); + + if (sym.getKind() == ElementKind.METHOD) { + sym.type.asMethodType().restype = type; + } else { + sym.type = type; + } + + sym.annotations.appendUniqueTypes(typeAnnotations); + if (sym.getKind() == ElementKind.PARAMETER && + sym.getQualifiedName().equals(names._this)) { + sym.owner.type.asMethodType().recvtype = type; + // note that the typeAnnotations will also be added to the owner below. + } + if (sym.getKind() == ElementKind.PARAMETER || + sym.getKind() == ElementKind.LOCAL_VARIABLE || + sym.getKind() == ElementKind.RESOURCE_VARIABLE || + sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { + // Make sure all type annotations from the symbol are also + // on the owner. + sym.owner.annotations.appendUniqueTypes(sym.getTypeAnnotationMirrors()); + } + } + + // This method has a similar purpose as + // {@link com.sun.tools.javac.parser.JavacParser.insertAnnotationsToMostInner(JCExpression, List, boolean)} + // We found a type annotation in a declaration annotation position, + // for example, on the return type. + // Such an annotation is _not_ part of an JCAnnotatedType tree and we therefore + // need to set its position explicitly. + // The method returns a copy of type that contains these annotations. + private static Type typeWithAnnotations(final JCTree typetree, final Type type, + final List annotations, Log log) { + // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n", + // typetree, type, annotations); + if (annotations.isEmpty()) { + return type; + } + if (type.hasTag(TypeTag.ARRAY)) { + Type toreturn; + Type.ArrayType tomodify; + Type.ArrayType arType; + { + Type touse = type; + if (type.getKind() == TypeKind.ANNOTATED) { + Type.AnnotatedType atype = (Type.AnnotatedType)type; + toreturn = new Type.AnnotatedType(atype.underlyingType); + ((Type.AnnotatedType)toreturn).typeAnnotations = atype.typeAnnotations; + touse = atype.underlyingType; + arType = (Type.ArrayType) touse; + tomodify = new Type.ArrayType(null, arType.tsym); + ((Type.AnnotatedType)toreturn).underlyingType = tomodify; + } else { + arType = (Type.ArrayType) touse; + tomodify = new Type.ArrayType(null, arType.tsym); + toreturn = tomodify; + } + } + JCArrayTypeTree arTree = arrayTypeTree(typetree); + + ListBuffer depth = ListBuffer.lb(); + depth = depth.append(TypePathEntry.ARRAY); + while (arType.elemtype.hasTag(TypeTag.ARRAY)) { + if (arType.elemtype.getKind() == TypeKind.ANNOTATED) { + Type.AnnotatedType aelemtype = (Type.AnnotatedType) arType.elemtype; + Type.AnnotatedType newAT = new Type.AnnotatedType(aelemtype.underlyingType); + tomodify.elemtype = newAT; + newAT.typeAnnotations = aelemtype.typeAnnotations; + arType = (Type.ArrayType) aelemtype.underlyingType; + tomodify = new Type.ArrayType(null, arType.tsym); + newAT.underlyingType = tomodify; + } else { + arType = (Type.ArrayType) arType.elemtype; + tomodify.elemtype = new Type.ArrayType(null, arType.tsym); + tomodify = (Type.ArrayType) tomodify.elemtype; + } + arTree = arrayTypeTree(arTree.elemtype); + depth = depth.append(TypePathEntry.ARRAY); + } + Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, log); + tomodify.elemtype = arelemType; + for (Attribute.TypeCompound a : annotations) { + TypeAnnotationPosition p = a.position; + p.location = p.location.prependList(depth.toList()); + } + return toreturn; + } else if (type.hasTag(TypeTag.TYPEVAR)) { + // Nothing to do for type variables. + return type; + } else { + Type enclTy = type; + Element enclEl = type.asElement(); + JCTree enclTr = typetree; + + while (enclEl != null && + enclEl.getKind() != ElementKind.PACKAGE && + enclTy != null && + enclTy.getKind() != TypeKind.NONE && + enclTy.getKind() != TypeKind.ERROR && + (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT || + enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE || + enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) { + // Iterate also over the type tree, not just the type: the type is already + // completely resolved and we cannot distinguish where the annotation + // belongs for a nested type. + if (enclTr.getKind() == JCTree.Kind.MEMBER_SELECT) { + // only change encl in this case. + enclTy = enclTy.getEnclosingType(); + enclEl = enclEl.getEnclosingElement(); + enclTr = ((JCFieldAccess)enclTr).getExpression(); + } else if (enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE) { + enclTr = ((JCTypeApply)enclTr).getType(); + } else { + // only other option because of while condition + enclTr = ((JCAnnotatedType)enclTr).getUnderlyingType(); + } + } + + /** We are trying to annotate some enclosing type, + * but nothing more exists. + */ + if (enclTy != null && + enclTy.getKind() == TypeKind.NONE && + (enclTr.getKind() == JCTree.Kind.IDENTIFIER || + enclTr.getKind() == JCTree.Kind.MEMBER_SELECT || + enclTr.getKind() == JCTree.Kind.PARAMETERIZED_TYPE || + enclTr.getKind() == JCTree.Kind.ANNOTATED_TYPE)) { + // TODO: also if it's "java. @A lang.Object", that is, + // if it's on a package? + log.error(enclTr.pos(), "cant.annotate.nested.type", enclTr.toString()); + return type; + } + + // At this point we have visited the part of the nested + // type that is written in the source code. + // Now count from here to the actual top-level class to determine + // the correct nesting. + + // The genericLocation for the annotation. + ListBuffer depth = ListBuffer.lb(); + + Type topTy = enclTy; + while (enclEl != null && + enclEl.getKind() != ElementKind.PACKAGE && + topTy != null && + topTy.getKind() != TypeKind.NONE && + topTy.getKind() != TypeKind.ERROR) { + topTy = topTy.getEnclosingType(); + enclEl = enclEl.getEnclosingElement(); + + if (topTy != null && topTy.getKind() != TypeKind.NONE) { + // Only count enclosing types. + depth = depth.append(TypePathEntry.INNER_TYPE); + } + } + + if (depth.nonEmpty()) { + // Only need to change the annotation positions + // if they are on an enclosed type. + for (Attribute.TypeCompound a : annotations) { + TypeAnnotationPosition p = a.position; + p.location = p.location.appendList(depth.toList()); + } + } + + Type ret = typeWithAnnotations(type, enclTy, annotations); + return ret; + } + } + + private static JCArrayTypeTree arrayTypeTree(JCTree typetree) { + if (typetree.getKind() == JCTree.Kind.ARRAY_TYPE) { + return (JCArrayTypeTree) typetree; + } else if (typetree.getKind() == JCTree.Kind.ANNOTATED_TYPE) { + return (JCArrayTypeTree) ((JCAnnotatedType)typetree).underlyingType; + } else { + Assert.error("Could not determine array type from type tree: " + typetree); + return null; + } + } + + /** Return a copy of the first type that only differs by + * inserting the annotations to the left-most/inner-most type + * or the type given by stopAt. + * + * We need the stopAt parameter to know where on a type to + * put the annotations. + * If we have nested classes Outer > Middle > Inner, and we + * have the source type "@A Middle.Inner", we will invoke + * this method with type = Outer.Middle.Inner, + * stopAt = Middle.Inner, and annotations = @A. + * + * @param type The type to copy. + * @param stopAt The type to stop at. + * @param annotations The annotations to insert. + * @return A copy of type that contains the annotations. + */ + private static Type typeWithAnnotations(final Type type, + final Type stopAt, + final List annotations) { + Visitor> visitor = + new Type.Visitor>() { + @Override + public Type visitClassType(ClassType t, List s) { + // assert that t.constValue() == null? + if (t == stopAt || + t.getEnclosingType() == Type.noType) { + return new AnnotatedType(s, t); + } else { + ClassType ret = new ClassType(t.getEnclosingType().accept(this, s), + t.typarams_field, t.tsym); + ret.all_interfaces_field = t.all_interfaces_field; + ret.allparams_field = t.allparams_field; + ret.interfaces_field = t.interfaces_field; + ret.rank_field = t.rank_field; + ret.supertype_field = t.supertype_field; + return ret; + } + } + + @Override + public Type visitAnnotatedType(AnnotatedType t, List s) { + return new AnnotatedType(t.typeAnnotations, t.underlyingType.accept(this, s)); + } + + @Override + public Type visitWildcardType(WildcardType t, List s) { + return new AnnotatedType(s, t); + } + + @Override + public Type visitArrayType(ArrayType t, List s) { + ArrayType ret = new ArrayType(t.elemtype.accept(this, s), t.tsym); + return ret; + } + + @Override + public Type visitMethodType(MethodType t, List s) { + // Impossible? + return t; + } + + @Override + public Type visitPackageType(PackageType t, List s) { + // Impossible? + return t; + } + + @Override + public Type visitTypeVar(TypeVar t, List s) { + return new AnnotatedType(s, t); + } + + @Override + public Type visitCapturedType(CapturedType t, List s) { + return new AnnotatedType(s, t); + } + + @Override + public Type visitForAll(ForAll t, List s) { + // Impossible? + return t; + } + + @Override + public Type visitUndetVar(UndetVar t, List s) { + // Impossible? + return t; + } + + @Override + public Type visitErrorType(ErrorType t, List s) { + return new AnnotatedType(s, t); + } + + @Override + public Type visitType(Type t, List s) { + // Error? + return t; + } + }; + + return type.accept(visitor, annotations); + } + + private static Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) { + // It is safe to alias the position. + return new Attribute.TypeCompound(a, p); + } + + private AnnotationType annotationType(Attribute.Compound a, Symbol s) { + Attribute.Compound atTarget = + a.type.tsym.attribute(syms.annotationTargetType.tsym); + if (atTarget == null) { + return inferTargetMetaInfo(a, s); + } + Attribute atValue = atTarget.member(names.value); + if (!(atValue instanceof Attribute.Array)) { + Assert.error("annotationType(): bad @Target argument " + atValue + + " (" + atValue.getClass() + ")"); + return AnnotationType.DECLARATION; // error recovery + } + Attribute.Array arr = (Attribute.Array) atValue; + boolean isDecl = false, isType = false; + for (Attribute app : arr.values) { + if (!(app instanceof Attribute.Enum)) { + Assert.error("annotationType(): unrecognized Attribute kind " + app + + " (" + app.getClass() + ")"); + isDecl = true; + continue; + } + Attribute.Enum e = (Attribute.Enum) app; + if (e.value.name == names.TYPE) { + if (s.kind == Kinds.TYP) + isDecl = true; + } else if (e.value.name == names.FIELD) { + if (s.kind == Kinds.VAR && + s.owner.kind != Kinds.MTH) + isDecl = true; + } else if (e.value.name == names.METHOD) { + if (s.kind == Kinds.MTH && + !s.isConstructor()) + isDecl = true; + } else if (e.value.name == names.PARAMETER) { + if (s.kind == Kinds.VAR && + s.owner.kind == Kinds.MTH && + (s.flags() & Flags.PARAMETER) != 0) + isDecl = true; + } else if (e.value.name == names.CONSTRUCTOR) { + if (s.kind == Kinds.MTH && + s.isConstructor()) + isDecl = true; + } else if (e.value.name == names.LOCAL_VARIABLE) { + if (s.kind == Kinds.VAR && + s.owner.kind == Kinds.MTH && + (s.flags() & Flags.PARAMETER) == 0) + isDecl = true; + } else if (e.value.name == names.ANNOTATION_TYPE) { + if (s.kind == Kinds.TYP && + (s.flags() & Flags.ANNOTATION) != 0) + isDecl = true; + } else if (e.value.name == names.PACKAGE) { + if (s.kind == Kinds.PCK) + isDecl = true; + } else if (e.value.name == names.TYPE_USE) { + if (s.kind == Kinds.TYP || + s.kind == Kinds.VAR || + (s.kind == Kinds.MTH && !s.isConstructor() && + !s.type.getReturnType().hasTag(TypeTag.VOID)) || + (s.kind == Kinds.MTH && s.isConstructor())) + isType = true; + } else if (e.value.name == names.TYPE_PARAMETER) { + /* Irrelevant in this case */ + // TYPE_PARAMETER doesn't aid in distinguishing between + // Type annotations and declaration annotations on an + // Element + } else { + Assert.error("annotationType(): unrecognized Attribute name " + e.value.name + + " (" + e.value.name.getClass() + ")"); + isDecl = true; + } + } + if (isDecl && isType) { + return AnnotationType.BOTH; + } else if (isType) { + return AnnotationType.TYPE; + } else { + return AnnotationType.DECLARATION; + } + } + + /** Infer the target annotation kind, if none is give. + * We only infer declaration annotations. + */ + private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) { + return AnnotationType.DECLARATION; + } + + + /* This is the beginning of the second part of organizing + * type annotations: determine the type annotation positions. + */ + + private void resolveFrame(JCTree tree, JCTree frame, + List path, TypeAnnotationPosition p) { + /* + System.out.println("Resolving tree: " + tree + " kind: " + tree.getKind()); + System.out.println(" Framing tree: " + frame + " kind: " + frame.getKind()); + */ + switch (frame.getKind()) { + case TYPE_CAST: + p.type = TargetType.CAST; + p.pos = frame.pos; + return; + + case INSTANCE_OF: + p.type = TargetType.INSTANCEOF; + p.pos = frame.pos; + return; + + case NEW_CLASS: + JCNewClass frameNewClass = (JCNewClass)frame; + if (frameNewClass.typeargs.contains(tree)) { + p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT; + p.type_index = frameNewClass.typeargs.indexOf(tree); + } else { + p.type = TargetType.NEW; + } + p.pos = frame.pos; + return; + + case NEW_ARRAY: + p.type = TargetType.NEW; + p.pos = frame.pos; + return; + + case ANNOTATION_TYPE: + case CLASS: + case ENUM: + case INTERFACE: + p.pos = frame.pos; + if (((JCClassDecl)frame).extending == tree) { + p.type = TargetType.CLASS_EXTENDS; + p.type_index = -1; + } else if (((JCClassDecl)frame).implementing.contains(tree)) { + p.type = TargetType.CLASS_EXTENDS; + p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree); + } else if (((JCClassDecl)frame).typarams.contains(tree)) { + p.type = TargetType.CLASS_TYPE_PARAMETER; + p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree); + } else { + Assert.error("Could not determine position of tree " + tree + + " within frame " + frame); + } + return; + + case METHOD: { + JCMethodDecl frameMethod = (JCMethodDecl) frame; + p.pos = frame.pos; + if (frameMethod.thrown.contains(tree)) { + p.type = TargetType.THROWS; + p.type_index = frameMethod.thrown.indexOf(tree); + } else if (frameMethod.restype == tree) { + p.type = TargetType.METHOD_RETURN; + } else if (frameMethod.typarams.contains(tree)) { + p.type = TargetType.METHOD_TYPE_PARAMETER; + p.parameter_index = frameMethod.typarams.indexOf(tree); + } else { + Assert.error("Could not determine position of tree " + tree + + " within frame " + frame); + } + return; + } + + case PARAMETERIZED_TYPE: { + if (((JCTypeApply)frame).clazz == tree) { + // generic: RAW; noop + } else if (((JCTypeApply)frame).arguments.contains(tree)) { + JCTypeApply taframe = (JCTypeApply) frame; + int arg = taframe.arguments.indexOf(tree); + p.location = p.location.prepend(new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg)); + + locateNestedTypes(taframe.type, p); + } else { + Assert.error("Could not determine type argument position of tree " + tree + + " within frame " + frame); + } + + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case ARRAY_TYPE: { + ListBuffer index = ListBuffer.lb(); + index = index.append(TypePathEntry.ARRAY); + List newPath = path.tail; + while (true) { + JCTree npHead = newPath.tail.head; + if (npHead.hasTag(JCTree.Tag.TYPEARRAY)) { + newPath = newPath.tail; + index = index.append(TypePathEntry.ARRAY); + } else if (npHead.hasTag(JCTree.Tag.ANNOTATED_TYPE)) { + newPath = newPath.tail; + } else { + break; + } + } + p.location = p.location.prependList(index.toList()); + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case TYPE_PARAMETER: + if (path.tail.tail.head.hasTag(JCTree.Tag.CLASSDEF)) { + JCClassDecl clazz = (JCClassDecl)path.tail.tail.head; + p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND; + p.parameter_index = clazz.typarams.indexOf(path.tail.head); + p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); + if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) { + // Account for an implicit Object as bound 0 + p.bound_index += 1; + } + } else if (path.tail.tail.head.hasTag(JCTree.Tag.METHODDEF)) { + JCMethodDecl method = (JCMethodDecl)path.tail.tail.head; + p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND; + p.parameter_index = method.typarams.indexOf(path.tail.head); + p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); + if (((JCTypeParameter)frame).bounds.get(0).type.isInterface()) { + // Account for an implicit Object as bound 0 + p.bound_index += 1; + } + } else { + Assert.error("Could not determine position of tree " + tree + + " within frame " + frame); + } + p.pos = frame.pos; + return; + + case VARIABLE: + VarSymbol v = ((JCVariableDecl)frame).sym; + p.pos = frame.pos; + switch (v.getKind()) { + case LOCAL_VARIABLE: + p.type = TargetType.LOCAL_VARIABLE; + break; + case FIELD: + p.type = TargetType.FIELD; + break; + case PARAMETER: + if (v.getQualifiedName().equals(names._this)) { + // TODO: Intro a separate ElementKind? + p.type = TargetType.METHOD_RECEIVER; + } else { + p.type = TargetType.METHOD_FORMAL_PARAMETER; + p.parameter_index = methodParamIndex(path, frame); + } + break; + case EXCEPTION_PARAMETER: + p.type = TargetType.EXCEPTION_PARAMETER; + break; + case RESOURCE_VARIABLE: + p.type = TargetType.RESOURCE_VARIABLE; + break; + default: + Assert.error("Found unexpected type annotation for variable: " + v + " with kind: " + v.getKind()); + } + return; + + case ANNOTATED_TYPE: { + if (frame == tree) { + // This is only true for the first annotated type we see. + // For any other annotated types along the path, we do + // not care about inner types. + JCAnnotatedType atypetree = (JCAnnotatedType) frame; + final Type utype = atypetree.underlyingType.type; + Symbol tsym = utype.tsym; + if (tsym.getKind().equals(ElementKind.TYPE_PARAMETER) || + utype.getKind().equals(TypeKind.WILDCARD) || + utype.getKind().equals(TypeKind.ARRAY)) { + // Type parameters, wildcards, and arrays have the declaring + // class/method as enclosing elements. + // There is actually nothing to do for them. + } else { + locateNestedTypes(utype, p); + } + } + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case UNION_TYPE: { + // TODO: can we store any information here to help in + // determining the final position? + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case METHOD_INVOCATION: { + JCMethodInvocation invocation = (JCMethodInvocation)frame; + if (!invocation.typeargs.contains(tree)) { + Assert.error("{" + tree + "} is not an argument in the invocation: " + invocation); + } + p.type = TargetType.METHOD_INVOCATION_TYPE_ARGUMENT; + p.pos = invocation.pos; + p.type_index = invocation.typeargs.indexOf(tree); + return; + } + + case EXTENDS_WILDCARD: + case SUPER_WILDCARD: { + // Annotations in wildcard bounds + p.location = p.location.prepend(TypePathEntry.WILDCARD); + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + case MEMBER_SELECT: { + List newPath = path.tail; + resolveFrame(newPath.head, newPath.tail.head, newPath, p); + return; + } + + default: + Assert.error("Unresolved frame: " + frame + " of kind: " + frame.getKind() + + "\n Looking for tree: " + tree); + return; + } + } + + private static void locateNestedTypes(Type type, TypeAnnotationPosition p) { + // The number of "steps" to get from the full type to the + // left-most outer type. + ListBuffer depth = ListBuffer.lb(); + + Type encl = type.getEnclosingType(); + while (encl != null && + encl.getKind() != TypeKind.NONE && + encl.getKind() != TypeKind.ERROR) { + depth = depth.append(TypePathEntry.INNER_TYPE); + encl = encl.getEnclosingType(); + } + if (depth.nonEmpty()) { + p.location = p.location.prependList(depth.toList()); + } + } + + private static int methodParamIndex(List path, JCTree param) { + List curr = path; + while (curr.head.getTag() != Tag.METHODDEF) { + curr = curr.tail; + } + JCMethodDecl method = (JCMethodDecl)curr.head; + return method.params.indexOf(param); + } + + // Each class (including enclosed inner classes) is visited separately. + // This flag is used to prevent from visiting inner classes. + private boolean isInClass = false; + + @Override + public void visitClassDef(JCClassDecl tree) { + if (isInClass) + return; + isInClass = true; + if (sigOnly) { + scan(tree.mods); + scan(tree.typarams); + scan(tree.extending); + scan(tree.implementing); + } + scan(tree.defs); + } + + /** + * Resolve declaration vs. type annotations in methods and + * then determine the positions. + */ + @Override + public void visitMethodDef(final JCMethodDecl tree) { + if (tree.sym == null) { + // Something most be wrong, e.g. a class not found. + // Quietly ignore. (See test FailOver15.java) + return; + } + if (sigOnly) { + { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.METHOD_RETURN; + if (tree.sym.isConstructor()) { + pos.pos = tree.pos; + // Use null to mark that the annotations go with the symbol. + separateAnnotationsKinds(tree, null, tree.sym, pos); + } else { + pos.pos = tree.restype.pos; + separateAnnotationsKinds(tree.restype, tree.sym.type.getReturnType(), + tree.sym, pos); + } + } + if (tree.recvparam != null && tree.recvparam.sym != null) { + // TODO: make sure there are no declaration annotations. + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.METHOD_RECEIVER; + pos.pos = tree.recvparam.vartype.pos; + separateAnnotationsKinds(tree.recvparam.vartype, tree.recvparam.sym.type, + tree.recvparam.sym, pos); + } + int i = 0; + for (JCVariableDecl param : tree.params) { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.METHOD_FORMAL_PARAMETER; + pos.parameter_index = i; + pos.pos = param.vartype.pos; + separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos); + ++i; + } + } + + push(tree); + // super.visitMethodDef(tree); + if (sigOnly) { + scan(tree.mods); + scan(tree.restype); + scan(tree.typarams); + scan(tree.recvparam); + scan(tree.params); + scan(tree.thrown); + } else { + scan(tree.defaultValue); + scan(tree.body); + } + pop(); + } + + /** + * Resolve declaration vs. type annotations in variable declarations and + * then determine the positions. + */ + @Override + public void visitVarDef(final JCVariableDecl tree) { + if (tree.sym == null) { + // Something is wrong already. Quietly ignore. + } else if (tree.sym.getKind() == ElementKind.FIELD) { + if (sigOnly) { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.FIELD; + pos.pos = tree.pos; + separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); + } + } else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.LOCAL_VARIABLE; + pos.pos = tree.pos; + separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); + } else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { + // System.out.println("Found exception param: " + tree); + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.EXCEPTION_PARAMETER; + pos.pos = tree.pos; + separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); + } else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) { + TypeAnnotationPosition pos = new TypeAnnotationPosition(); + pos.type = TargetType.RESOURCE_VARIABLE; + pos.pos = tree.pos; + separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos); + } else { + // There is nothing else in a variable declaration that needs separation. + // System.out.println("We found a: " + tree); + } + + push(tree); + // super.visitVarDef(tree); + scan(tree.mods); + scan(tree.vartype); + if (!sigOnly) { + scan(tree.init); + } + pop(); + } + + @Override + public void visitBlock(JCBlock tree) { + // Do not descend into top-level blocks when only interested + // in the signature. + if (!sigOnly) { + scan(tree.stats); + } + } + + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + push(tree); + findPosition(tree, tree, tree.annotations); + pop(); + super.visitAnnotatedType(tree); + } + + @Override + public void visitTypeParameter(JCTypeParameter tree) { + findPosition(tree, peek2(), tree.annotations); + super.visitTypeParameter(tree); + } + + @Override + public void visitNewArray(JCNewArray tree) { + findPosition(tree, tree, tree.annotations); + int dimAnnosCount = tree.dimAnnotations.size(); + ListBuffer depth = ListBuffer.lb(); + + // handle annotations associated with dimensions + for (int i = 0; i < dimAnnosCount; ++i) { + TypeAnnotationPosition p = new TypeAnnotationPosition(); + p.pos = tree.pos; + p.type = TargetType.NEW; + if (i != 0) { + depth = depth.append(TypePathEntry.ARRAY); + p.location = p.location.appendList(depth.toList()); + } + + setTypeAnnotationPos(tree.dimAnnotations.get(i), p); + } + + // handle "free" annotations + // int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1; + // TODO: is depth.size == i here? + JCExpression elemType = tree.elemtype; + while (elemType != null) { + if (elemType.hasTag(JCTree.Tag.ANNOTATED_TYPE)) { + JCAnnotatedType at = (JCAnnotatedType)elemType; + TypeAnnotationPosition p = new TypeAnnotationPosition(); + p.type = TargetType.NEW; + p.pos = tree.pos; + p.location = p.location.appendList(depth.toList()); + setTypeAnnotationPos(at.annotations, p); + elemType = at.underlyingType; + } else if (elemType.hasTag(JCTree.Tag.TYPEARRAY)) { + depth = depth.append(TypePathEntry.ARRAY); + elemType = ((JCArrayTypeTree)elemType).elemtype; + } else { + break; + } + } + scan(tree.elems); + } + + private void findPosition(JCTree tree, JCTree frame, List annotations) { + if (!annotations.isEmpty()) { + /* + System.out.println("Finding pos for: " + annotations); + System.out.println(" tree: " + tree); + System.out.println(" frame: " + frame); + */ + TypeAnnotationPosition p = new TypeAnnotationPosition(); + resolveFrame(tree, frame, frames.toList(), p); + setTypeAnnotationPos(annotations, p); + } + } + + private static void setTypeAnnotationPos(List annotations, + TypeAnnotationPosition position) { + for (JCAnnotation anno : annotations) { + ((Attribute.TypeCompound) anno.attribute).position = position; + } + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index a7378f8acfe..f7fa66625ef 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,13 +34,14 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import javax.lang.model.type.TypeKind; + import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; import com.sun.tools.javac.comp.Check; import com.sun.tools.javac.jvm.ClassReader; import com.sun.tools.javac.util.*; -import com.sun.tools.javac.util.List; import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Scope.*; @@ -354,8 +355,29 @@ public class Types { return descSym; } - public Type getType(Type origin) { - return memberType(origin, descSym); + public Type getType(Type site) { + if (capture(site) != site) { + Type formalInterface = site.tsym.type; + ListBuffer typeargs = ListBuffer.lb(); + List actualTypeargs = site.getTypeArguments(); + //simply replace the wildcards with its bound + for (Type t : formalInterface.getTypeArguments()) { + if (actualTypeargs.head.hasTag(WILDCARD)) { + WildcardType wt = (WildcardType)actualTypeargs.head; + typeargs.append(wt.type); + } else { + typeargs.append(actualTypeargs.head); + } + actualTypeargs = actualTypeargs.tail; + } + site = subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList()); + if (!chk.checkValidGenericType(site)) { + //if the inferred functional interface type is not well-formed, + //or if it's not a subtype of the original target, issue an error + throw failure(diags.fragment("no.suitable.functional.intf.inst", site)); + } + } + return memberType(site, descSym); } } @@ -392,9 +414,9 @@ public class Types { * Compute the function descriptor associated with a given functional interface */ public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError { - if (!origin.isInterface()) { + if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) { //t must be an interface - throw failure("not.a.functional.intf"); + throw failure("not.a.functional.intf", origin); } final ListBuffer abstracts = ListBuffer.lb(); @@ -406,13 +428,13 @@ public class Types { abstracts.append(sym); } else { //the target method(s) should be the only abstract members of t - throw failure("not.a.functional.intf.1", + throw failure("not.a.functional.intf.1", origin, diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin)); } } if (abstracts.isEmpty()) { //t must define a suitable non-generic method - throw failure("not.a.functional.intf.1", + throw failure("not.a.functional.intf.1", origin, diags.fragment("no.abstracts", Kinds.kindName(origin), origin)); } else if (abstracts.size() == 1) { return new FunctionDescriptor(abstracts.first()); @@ -553,6 +575,15 @@ public class Types { return false; } } + + public boolean isFunctionalInterface(Type site) { + try { + findDescriptorType(site); + return true; + } catch (FunctionDescriptorLookupError ex) { + return false; + } + } // /** @@ -654,6 +685,8 @@ public class Types { //where private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) { if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) { + t = t.unannotatedType(); + s = s.unannotatedType(); if (((ArrayType)t).elemtype.isPrimitive()) { return isSameType(elemtype(t), elemtype(s)); } else { @@ -679,7 +712,10 @@ public class Types { } private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) { - if (t.tag != ARRAY || isReifiable(t)) return; + if (t.tag != ARRAY || isReifiable(t)) + return; + t = t.unannotatedType(); + s = s.unannotatedType(); ArrayType from = (ArrayType)t; boolean shouldWarn = false; switch (s.tag) { @@ -709,6 +745,12 @@ public class Types { return isSubtype(t, s, false); } public boolean isSubtype(Type t, Type s, boolean capture) { + if (t == s) + return true; + + t = t.unannotatedType(); + s = s.unannotatedType(); + if (t == s) return true; @@ -1653,6 +1695,7 @@ public class Types { case WILDCARD: return elemtype(upperBound(t)); case ARRAY: + t = t.unannotatedType(); return ((ArrayType)t).elemtype; case FORALL: return elemtype(((ForAll)t).qtype); @@ -1981,6 +2024,11 @@ public class Types { public Type visitErrorType(ErrorType t, Boolean recurse) { return t; } + + @Override + public Type visitAnnotatedType(AnnotatedType t, Boolean recurse) { + return new AnnotatedType(t.typeAnnotations, erasure(t.underlyingType, recurse)); + } }; private Mapping erasureFun = new Mapping ("erasure") { @@ -2923,6 +2971,7 @@ public class Types { * graph. Undefined for all but reference types. */ public int rank(Type t) { + t = t.unannotatedType(); switch(t.tag) { case CLASS: { ClassType cls = (ClassType)t; @@ -3624,6 +3673,7 @@ public class Types { t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments()); } } + t = t.unannotatedType(); ClassType cls = (ClassType)t; if (cls.isRaw() || !cls.isParameterized()) return cls; @@ -4142,6 +4192,8 @@ public class Types { public R visitForAll(ForAll t, S s) { return visitType(t, s); } public R visitUndetVar(UndetVar t, S s) { return visitType(t, s); } public R visitErrorType(ErrorType t, S s) { return visitType(t, s); } + // Pretend annotations don't exist + public R visitAnnotatedType(AnnotatedType t, S s) { return visit(t.underlyingType, s); } } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java index b9807d9180c..678d2c2bb6a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.tools.javac.comp; import java.util.Map; + import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.*; @@ -87,20 +88,30 @@ public class Annotate { private int enterCount = 0; ListBuffer q = new ListBuffer(); + ListBuffer typesQ = new ListBuffer(); ListBuffer repeatedQ = new ListBuffer(); - - public void normal(Annotator a) { - q.append(a); - } + ListBuffer afterRepeatedQ = new ListBuffer(); public void earlier(Annotator a) { q.prepend(a); } + public void normal(Annotator a) { + q.append(a); + } + + public void typeAnnotation(Annotator a) { + typesQ.append(a); + } + public void repeated(Annotator a) { repeatedQ.append(a); } + public void afterRepeated(Annotator a) { + afterRepeatedQ.append(a); + } + /** Called when the Enter phase starts. */ public void enterStart() { enterCount++; @@ -116,12 +127,18 @@ public class Annotate { if (enterCount != 0) return; enterCount++; try { - while (q.nonEmpty()) + while (q.nonEmpty()) { q.next().enterAnnotation(); - + } + while (typesQ.nonEmpty()) { + typesQ.next().enterAnnotation(); + } while (repeatedQ.nonEmpty()) { repeatedQ.next().enterAnnotation(); } + while (afterRepeatedQ.nonEmpty()) { + afterRepeatedQ.next().enterAnnotation(); + } } finally { enterCount--; } @@ -141,16 +158,18 @@ public class Annotate { * This context contains all the information needed to synthesize new * annotations trees by the completer for repeating annotations. */ - public class AnnotateRepeatedContext { + public class AnnotateRepeatedContext { public final Env env; - public final Map> annotated; - public final Map pos; + public final Map> annotated; + public final Map pos; public final Log log; + public final boolean isTypeCompound; public AnnotateRepeatedContext(Env env, - Map> annotated, - Map pos, - Log log) { + Map> annotated, + Map pos, + Log log, + boolean isTypeCompound) { Assert.checkNonNull(env); Assert.checkNonNull(annotated); Assert.checkNonNull(pos); @@ -160,6 +179,7 @@ public class Annotate { this.annotated = annotated; this.pos = pos; this.log = log; + this.isTypeCompound = isTypeCompound; } /** @@ -170,7 +190,7 @@ public class Annotate { * @param repeatingAnnotations a List of repeating annotations * @return a new Attribute.Compound that is the container for the repeatingAnnotations */ - public Attribute.Compound processRepeatedAnnotations(List repeatingAnnotations, Symbol sym) { + public T processRepeatedAnnotations(List repeatingAnnotations, Symbol sym) { return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this, sym); } @@ -246,7 +266,12 @@ public class Annotate { ((MethodSymbol)method, value)); t.type = result; } - return new Attribute.Compound(a.type, buf.toList()); + // TODO: this should be a TypeCompound if "a" is a JCTypeAnnotation. + // However, how do we find the correct position? + Attribute.Compound ac = new Attribute.Compound(a.type, buf.toList()); + // TODO: is this something we want? Who would use it? + // a.attribute = ac; + return ac; } Attribute enterAttributeValue(Type expected, @@ -329,6 +354,15 @@ public class Annotate { return new Attribute.Error(attr.attribExpr(tree, env, expected)); } + Attribute.TypeCompound enterTypeAnnotation(JCAnnotation a, + Type expected, + Env env) { + Attribute.Compound c = enterAnnotation(a, expected, env); + Attribute.TypeCompound tc = new Attribute.TypeCompound(c.type, c.values, new TypeAnnotationPosition()); + a.attribute = tc; + return tc; + } + /* ********************************* * Support for repeating annotations ***********************************/ @@ -337,10 +371,10 @@ public class Annotate { * synthesized container annotation or null IFF all repeating * annotation are invalid. This method reports errors/warnings. */ - private Attribute.Compound processRepeatedAnnotations(List annotations, - AnnotateRepeatedContext ctx, - Symbol on) { - Attribute.Compound firstOccurrence = annotations.head; + private T processRepeatedAnnotations(List annotations, + AnnotateRepeatedContext ctx, + Symbol on) { + T firstOccurrence = annotations.head; List repeated = List.nil(); Type origAnnoType = null; Type arrayOfOrigAnnoType = null; @@ -350,16 +384,16 @@ public class Annotate { Assert.check(!annotations.isEmpty() && !annotations.tail.isEmpty()); // i.e. size() > 1 - for (List al = annotations; + for (List al = annotations; !al.isEmpty(); al = al.tail) { - Attribute.Compound currentAnno = al.head; + T currentAnno = al.head; origAnnoType = currentAnno.type; if (arrayOfOrigAnnoType == null) { arrayOfOrigAnnoType = types.makeArrayType(origAnnoType); -} + } Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno)); if (currentContainerType == null) { @@ -383,25 +417,46 @@ public class Annotate { if (!repeated.isEmpty()) { repeated = repeated.reverse(); - JCAnnotation annoTree; TreeMaker m = make.at(ctx.pos.get(firstOccurrence)); Pair p = new Pair(containerValueSymbol, new Attribute.Array(arrayOfOrigAnnoType, repeated)); - annoTree = m.Annotation(new Attribute.Compound(targetContainerType, - List.of(p))); + if (ctx.isTypeCompound) { + /* TODO: the following code would be cleaner: + Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p), + ((Attribute.TypeCompound)annotations.head).position); + JCTypeAnnotation annoTree = m.TypeAnnotation(at); + at = enterTypeAnnotation(annoTree, targetContainerType, ctx.env); + */ + // However, we directly construct the TypeCompound to keep the + // direct relation to the contained TypeCompounds. + Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p), + ((Attribute.TypeCompound)annotations.head).position); - if (!chk.annotationApplicable(annoTree, on)) - log.error(annoTree.pos(), "invalid.containedby.annotation.incompatible.target", targetContainerType, origAnnoType); + // TODO: annotation applicability checks from below? - if (!chk.validateAnnotationDeferErrors(annoTree)) - log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); + at.setSynthesized(true); - Attribute.Compound c = enterAnnotation(annoTree, - targetContainerType, - ctx.env); - c.setSynthesized(true); - return c; + @SuppressWarnings("unchecked") + T x = (T) at; + return x; + } else { + Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p)); + JCAnnotation annoTree = m.Annotation(c); + + if (!chk.annotationApplicable(annoTree, on)) + log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType); + + if (!chk.validateAnnotationDeferErrors(annoTree)) + log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); + + c = enterAnnotation(annoTree, targetContainerType, ctx.env); + c.setSynthesized(true); + + @SuppressWarnings("unchecked") + T x = (T) c; + return x; + } } else { return null; // errors should have been reported elsewhere } @@ -414,11 +469,11 @@ public class Annotate { Type origAnnoType = currentAnno.type; TypeSymbol origAnnoDecl = origAnnoType.tsym; - // Fetch the ContainedBy annotation from the current + // Fetch the Repeatable annotation from the current // annotation's declaration, or null if it has none - Attribute.Compound ca = origAnnoDecl.attribute(syms.containedByType.tsym); - if (ca == null) { // has no ContainedBy annotation - log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.containedByType); + Attribute.Compound ca = origAnnoDecl.attribute(syms.repeatableType.tsym); + if (ca == null) { // has no Repeatable annotation + log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.repeatableType); return null; } @@ -440,23 +495,23 @@ public class Annotate { DiagnosticPosition pos, TypeSymbol annoDecl) { - // The next three checks check that the ContainedBy annotation + // The next three checks check that the Repeatable annotation // on the declaration of the annotation type that is repeating is // valid. - // ContainedBy must have at least one element + // Repeatable must have at least one element if (ca.values.isEmpty()) { - log.error(pos, "invalid.containedby.annotation", annoDecl); + log.error(pos, "invalid.repeatable.annotation", annoDecl); return null; } Pair p = ca.values.head; Name name = p.fst.name; if (name != names.value) { // should contain only one element, named "value" - log.error(pos, "invalid.containedby.annotation", annoDecl); + log.error(pos, "invalid.repeatable.annotation", annoDecl); return null; } if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class - log.error(pos, "invalid.containedby.annotation", annoDecl); + log.error(pos, "invalid.repeatable.annotation", annoDecl); return null; } @@ -491,13 +546,13 @@ public class Annotate { } if (error) { log.error(pos, - "invalid.containedby.annotation.multiple.values", + "invalid.repeatable.annotation.multiple.values", targetContainerType, nr_value_elems); return null; } else if (nr_value_elems == 0) { log.error(pos, - "invalid.containedby.annotation.no.value", + "invalid.repeatable.annotation.no.value", targetContainerType); return null; } @@ -506,7 +561,7 @@ public class Annotate { // probably "impossible" to fail this if (containerValueSymbol.kind != Kinds.MTH) { log.error(pos, - "invalid.containedby.annotation.invalid.value", + "invalid.repeatable.annotation.invalid.value", targetContainerType); fatalError = true; } @@ -518,7 +573,7 @@ public class Annotate { if (!(types.isArray(valueRetType) && types.isSameType(expectedType, valueRetType))) { log.error(pos, - "invalid.containedby.annotation.value.return", + "invalid.repeatable.annotation.value.return", targetContainerType, valueRetType, expectedType); @@ -528,10 +583,7 @@ public class Annotate { fatalError = true; } - // Explicitly no check for/validity of @ContainerFor. That is - // done on declaration of the container, and at reflect time. - - // The rest of the conditions for a valid containing annotation are made + // The conditions for a valid containing annotation are made // in Check.validateRepeatedAnnotaton(); return fatalError ? null : containerValueSymbol; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index da982534deb..db09cf5ed9b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -26,9 +26,9 @@ package com.sun.tools.javac.comp; import java.util.*; -import java.util.Set; import javax.lang.model.element.ElementKind; +import javax.lang.model.type.TypeKind; import javax.tools.JavaFileObject; import com.sun.source.tree.IdentifierTree; @@ -45,9 +45,9 @@ import com.sun.tools.javac.comp.DeferredAttr.AttrMode; import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; import com.sun.tools.javac.jvm.*; -import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; @@ -879,6 +879,7 @@ public class Attr extends JCTree.Visitor { deferredLintHandler.flush(tree.pos()); chk.checkDeprecatedAnnotation(tree.pos(), m); + // Create a new environment with local scope // for attributing the method. Env localEnv = memberEnter.methodEnv(tree, env); @@ -922,6 +923,21 @@ public class Attr extends JCTree.Visitor { // Check that result type is well-formed. chk.validate(tree.restype, localEnv); + // Check that receiver type is well-formed. + if (tree.recvparam != null) { + // Use a new environment to check the receiver parameter. + // Otherwise I get "might not have been initialized" errors. + // Is there a better way? + Env newEnv = memberEnter.methodEnv(tree, env); + attribType(tree.recvparam, newEnv); + chk.validate(tree.recvparam, newEnv); + if (!(tree.recvparam.type == m.owner.type || types.isSameType(tree.recvparam.type, m.owner.type))) { + // The == covers the common non-generic case, but for generic classes we need isSameType; + // note that equals didn't work. + log.error(tree.recvparam.pos(), "incorrect.receiver.type"); + } + } + // annotation method checks if ((owner.flags() & ANNOTATION) != 0) { // annotation method cannot have throws clause @@ -953,8 +969,7 @@ public class Attr extends JCTree.Visitor { // Empty bodies are only allowed for // abstract, native, or interface methods, or for methods // in a retrofit signature class. - if (isDefaultMethod || ((owner.flags() & INTERFACE) == 0 && - (tree.mods.flags & (ABSTRACT | NATIVE)) == 0) && + if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 && !relax) log.error(tree.pos(), "missing.meth.body.or.decl.abstract"); if (tree.defaultValue != null) { @@ -996,9 +1011,14 @@ public class Attr extends JCTree.Visitor { } } + // Attribute all type annotations in the body + memberEnter.typeAnnotate(tree.body, localEnv, m); + annotate.flush(); + // Attribute method body. attribStat(tree.body, localEnv); } + localEnv.info.scope.leave(); result = tree.type = m.type; chk.validateAnnotations(tree.mods.annotations, m); @@ -1019,6 +1039,12 @@ public class Attr extends JCTree.Visitor { memberEnter.memberEnter(tree, env); annotate.flush(); } + } else { + if (tree.init != null) { + // Field initializer expression need to be entered. + memberEnter.typeAnnotate(tree.init, env, tree.sym); + annotate.flush(); + } } VarSymbol v = tree.sym; @@ -1076,6 +1102,11 @@ public class Attr extends JCTree.Visitor { new MethodSymbol(tree.flags | BLOCK, names.empty, null, env.info.scope.owner); if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++; + + // Attribute all type annotations in the block + memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner); + annotate.flush(); + attribStats(tree.stats, localEnv); } else { // Create a new local environment with a local scope. @@ -1376,18 +1407,19 @@ public class Attr extends JCTree.Visitor { public void visitConditional(JCConditional tree) { Type condtype = attribExpr(tree.cond, env, syms.booleanType); - boolean standaloneConditional = !allowPoly || + tree.polyKind = (!allowPoly || pt().hasTag(NONE) && pt() != Type.recoveryType || - isBooleanOrNumeric(env, tree); + isBooleanOrNumeric(env, tree)) ? + PolyKind.STANDALONE : PolyKind.POLY; - if (!standaloneConditional && resultInfo.pt.hasTag(VOID)) { + if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) { //cannot get here (i.e. it means we are returning from void method - which is already an error) resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void")); result = tree.type = types.createErrorType(resultInfo.pt); return; } - ResultInfo condInfo = standaloneConditional ? + ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? unknownExprInfo : resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) { //this will use enclosing check context to check compatibility of @@ -1402,7 +1434,7 @@ public class Attr extends JCTree.Visitor { Type truetype = attribTree(tree.truepart, env, condInfo); Type falsetype = attribTree(tree.falsepart, env, condInfo); - Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt(); + Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt(); if (condtype.constValue() != null && truetype.constValue() != null && falsetype.constValue() != null && @@ -1424,12 +1456,30 @@ public class Attr extends JCTree.Visitor { JCConditional condTree = (JCConditional)tree; return isBooleanOrNumeric(env, condTree.truepart) && isBooleanOrNumeric(env, condTree.falsepart); + case APPLY: + JCMethodInvocation speculativeMethodTree = + (JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo); + Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType(); + return types.unboxedTypeOrType(owntype).isPrimitive(); + case NEWCLASS: + JCExpression className = + removeClassParams.translate(((JCNewClass)tree).clazz); + JCExpression speculativeNewClassTree = + (JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo); + return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive(); default: Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type; speculativeType = types.unboxedTypeOrType(speculativeType); return speculativeType.isPrimitive(); } } + //where + TreeTranslator removeClassParams = new TreeTranslator() { + @Override + public void visitTypeApply(JCTypeApply tree) { + result = translate(tree.clazz); + } + }; /** Compute the type of a conditional expression, after * checking that it exists. See JLS 15.25. Does not take into @@ -1828,10 +1878,24 @@ public class Attr extends JCTree.Visitor { // If enclosing class is given, attribute it, and // complete class name to be fully qualified JCExpression clazz = tree.clazz; // Class field following new - JCExpression clazzid = // Identifier in class field - (clazz.hasTag(TYPEAPPLY)) - ? ((JCTypeApply) clazz).clazz - : clazz; + JCExpression clazzid; // Identifier in class field + JCAnnotatedType annoclazzid; // Annotated type enclosing clazzid + annoclazzid = null; + + if (clazz.hasTag(TYPEAPPLY)) { + clazzid = ((JCTypeApply) clazz).clazz; + if (clazzid.hasTag(ANNOTATED_TYPE)) { + annoclazzid = (JCAnnotatedType) clazzid; + clazzid = annoclazzid.underlyingType; + } + } else { + if (clazz.hasTag(ANNOTATED_TYPE)) { + annoclazzid = (JCAnnotatedType) clazz; + clazzid = annoclazzid.underlyingType; + } else { + clazzid = clazz; + } + } JCExpression clazzid1 = clazzid; // The same in fully qualified form @@ -1846,14 +1910,30 @@ public class Attr extends JCTree.Visitor { // yields a clazz T.C. Type encltype = chk.checkRefType(tree.encl.pos(), attribExpr(tree.encl, env)); + // TODO 308: in .new C, do we also want to add the type annotations + // from expr to the combined type, or not? Yes, do this. clazzid1 = make.at(clazz.pos).Select(make.Type(encltype), ((JCIdent) clazzid).name); - if (clazz.hasTag(TYPEAPPLY)) - clazz = make.at(tree.pos). + + if (clazz.hasTag(ANNOTATED_TYPE)) { + JCAnnotatedType annoType = (JCAnnotatedType) clazz; + List annos = annoType.annotations; + + if (annoType.underlyingType.hasTag(TYPEAPPLY)) { + clazzid1 = make.at(tree.pos). + TypeApply(clazzid1, + ((JCTypeApply) clazz).arguments); + } + + clazzid1 = make.at(tree.pos). + AnnotatedType(annos, clazzid1); + } else if (clazz.hasTag(TYPEAPPLY)) { + clazzid1 = make.at(tree.pos). TypeApply(clazzid1, ((JCTypeApply) clazz).arguments); - else - clazz = clazzid1; + } + + clazz = clazzid1; } // Attribute clazz expression and store @@ -1870,6 +1950,9 @@ public class Attr extends JCTree.Visitor { tree.clazz.type = clazztype; TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1)); clazzid.type = ((JCIdent) clazzid).sym.type; + if (annoclazzid != null) { + annoclazzid.type = clazzid.type; + } if (!clazztype.isErroneous()) { if (cdef != null && clazztype.tsym.isInterface()) { log.error(tree.encl.pos(), "anon.class.impl.intf.no.qual.for.new"); @@ -2173,17 +2256,18 @@ public class Attr extends JCTree.Visitor { boolean needsRecovery = resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK; try { + Type target = pt(); List explicitParamTypes = null; - if (TreeInfo.isExplicitLambda(that)) { + if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) { //attribute lambda parameters attribStats(that.params, localEnv); explicitParamTypes = TreeInfo.types(that.params); + target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext); } - Type target; Type lambdaType; if (pt() != Type.recoveryType) { - target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), explicitParamTypes, resultInfo.checkContext); + target = checkIntersectionTarget(that, target, resultInfo.checkContext); lambdaType = types.findDescriptorType(target); chk.checkFunctionalInterface(that, target); } else { @@ -2191,6 +2275,8 @@ public class Attr extends JCTree.Visitor { lambdaType = fallbackDescriptorType(that); } + setFunctionalInfo(that, pt(), lambdaType, resultInfo.checkContext.inferenceContext()); + if (lambdaType.hasTag(FORALL)) { //lambda expression target desc cannot be a generic method resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", @@ -2199,7 +2285,7 @@ public class Attr extends JCTree.Visitor { return; } - if (!TreeInfo.isExplicitLambda(that)) { + if (that.paramKind == JCLambda.ParameterKind.IMPLICIT) { //add param type info in the AST List actuals = lambdaType.getParameterTypes(); List params = that.params; @@ -2282,8 +2368,7 @@ public class Attr extends JCTree.Visitor { } } - private Type checkIntersectionTarget(DiagnosticPosition pos, ResultInfo resultInfo) { - Type pt = resultInfo.pt; + private Type checkIntersectionTarget(DiagnosticPosition pos, Type pt, CheckContext checkContext) { if (pt != Type.recoveryType && pt.isCompound()) { IntersectionClassType ict = (IntersectionClassType)pt; List bounds = ict.allInterfaces ? @@ -2292,7 +2377,7 @@ public class Attr extends JCTree.Visitor { types.findDescriptorType(bounds.head); //propagate exception outwards! for (Type bound : bounds.tail) { if (!types.isMarkerInterface(bound)) { - resultInfo.checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound)); + checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound)); } } //for now (translation doesn't support intersection types) @@ -2355,9 +2440,9 @@ public class Attr extends JCTree.Visitor { @Override public boolean compatible(Type found, Type req, Warner warn) { //return type must be compatible in both current context and assignment context - return types.isAssignable(found, inferenceContext().asFree(req, types), warn) && - super.compatible(found, req, warn); + return chk.basicHandler.compatible(found, inferenceContext().asFree(req, types), warn); } + @Override public void report(DiagnosticPosition pos, JCDiagnostic details) { enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details)); @@ -2473,7 +2558,7 @@ public class Attr extends JCTree.Visitor { Type target; Type desc; if (pt() != Type.recoveryType) { - target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), null, resultInfo.checkContext); + target = checkIntersectionTarget(that, pt(), resultInfo.checkContext); desc = types.findDescriptorType(target); chk.checkFunctionalInterface(that, target); } else { @@ -2481,12 +2566,11 @@ public class Attr extends JCTree.Visitor { desc = fallbackDescriptorType(that); } + setFunctionalInfo(that, pt(), desc, resultInfo.checkContext.inferenceContext()); List argtypes = desc.getParameterTypes(); - boolean allowBoxing = - resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired(); Pair refResult = rs.resolveMemberReference(that.pos(), localEnv, that, - that.expr.type, that.name, argtypes, typeargtypes, allowBoxing); + that.expr.type, that.name, argtypes, typeargtypes, true); Symbol refSym = refResult.fst; Resolve.ReferenceLookupHelper lookupHelper = refResult.snd; @@ -2635,6 +2719,34 @@ public class Attr extends JCTree.Visitor { } } + /** + * Set functional type info on the underlying AST. Note: as the target descriptor + * might contain inference variables, we might need to register an hook in the + * current inference context. + */ + private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, final Type descriptorType, InferenceContext inferenceContext) { + if (inferenceContext.free(descriptorType)) { + inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { + public void typesInferred(InferenceContext inferenceContext) { + setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType, types), inferenceContext); + } + }); + } else { + ListBuffer targets = ListBuffer.lb(); + if (pt.hasTag(CLASS)) { + if (pt.isCompound()) { + for (Type t : ((IntersectionClassType)pt()).interfaces_field) { + targets.append(t.tsym); + } + } else { + targets.append(pt.tsym); + } + } + fExpr.targets = targets.toList(); + fExpr.descriptorType = descriptorType; + } + } + public void visitParens(JCParens tree) { Type owntype = attribTree(tree.expr, env, resultInfo); result = check(tree, owntype, pkind(), resultInfo); @@ -3207,8 +3319,18 @@ public class Attr extends JCTree.Visitor { // Tree.Visitor. else if (ownOuter.hasTag(CLASS) && site != ownOuter) { Type normOuter = site; - if (normOuter.hasTag(CLASS)) + if (normOuter.hasTag(CLASS)) { normOuter = types.asEnclosingSuper(site, ownOuter.tsym); + if (site.getKind() == TypeKind.ANNOTATED) { + // Propagate any type annotations. + // TODO: should asEnclosingSuper do this? + // Note that the type annotations in site will be updated + // by annotateType. Therefore, modify site instead + // of creating a new AnnotatedType. + ((AnnotatedType)site).underlyingType = normOuter; + normOuter = site; + } + } if (normOuter == null) // perhaps from an import normOuter = types.erasure(ownOuter); if (normOuter != ownOuter) @@ -3432,6 +3554,15 @@ public class Attr extends JCTree.Visitor { env.info.defaultSuperCallSite = null; } + if (sym.isStatic() && site.isInterface()) { + Assert.check(env.tree.hasTag(APPLY)); + JCMethodInvocation app = (JCMethodInvocation)env.tree; + if (app.meth.hasTag(SELECT) && + !TreeInfo.isStaticSelector(((JCFieldAccess)app.meth).selected, names)) { + log.error(env.tree.pos(), "illegal.static.intf.meth.call", site); + } + } + // Compute the identifier's instantiated type. // For methods, we need to compute the instance type by // Resolve.instantiate from the symbol's type as well as @@ -3587,8 +3718,15 @@ public class Attr extends JCTree.Visitor { tree.type = result = checkIntersection(tree, tree.bounds); } - public void visitTypeParameter(JCTypeParameter tree) { - TypeVar typeVar = (TypeVar)tree.type; + public void visitTypeParameter(JCTypeParameter tree) { + TypeVar typeVar = (TypeVar) tree.type; + + if (tree.annotations != null && tree.annotations.nonEmpty()) { + AnnotatedType antype = new AnnotatedType(typeVar); + annotateType(antype, tree.annotations); + tree.type = antype; + } + if (!typeVar.bound.isErroneous()) { //fixup type-parameter bound computed in 'attribTypeVariables' typeVar.bound = checkIntersection(tree, tree.bounds); @@ -3684,6 +3822,44 @@ public class Attr extends JCTree.Visitor { result = tree.type = syms.errType; } + public void visitAnnotatedType(JCAnnotatedType tree) { + Type underlyingType = attribType(tree.getUnderlyingType(), env); + this.attribAnnotationTypes(tree.annotations, env); + AnnotatedType antype = new AnnotatedType(underlyingType); + annotateType(antype, tree.annotations); + result = tree.type = antype; + } + + /** + * Apply the annotations to the particular type. + */ + public void annotateType(final AnnotatedType type, final List annotations) { + if (annotations.isEmpty()) + return; + annotate.typeAnnotation(new Annotate.Annotator() { + @Override + public String toString() { + return "annotate " + annotations + " onto " + type; + } + @Override + public void enterAnnotation() { + List compounds = fromAnnotations(annotations); + type.typeAnnotations = compounds; + } + }); + } + + private static List fromAnnotations(List annotations) { + if (annotations.isEmpty()) + return List.nil(); + + ListBuffer buf = ListBuffer.lb(); + for (JCAnnotation anno : annotations) { + buf.append((Attribute.TypeCompound) anno.attribute); + } + return buf.toList(); + } + public void visitErroneous(JCErroneous tree) { if (tree.errs != null) for (JCTree err : tree.errs) @@ -3844,24 +4020,14 @@ public class Attr extends JCTree.Visitor { log.error(tree.typarams.head.pos(), "intf.annotation.cant.have.type.params"); - // If this annotation has a @ContainedBy, validate - Attribute.Compound containedBy = c.attribute(syms.containedByType.tsym); - if (containedBy != null) { - // get diagnositc position for error reporting - DiagnosticPosition cbPos = getDiagnosticPosition(tree, containedBy.type); + // If this annotation has a @Repeatable, validate + Attribute.Compound repeatable = c.attribute(syms.repeatableType.tsym); + if (repeatable != null) { + // get diagnostic position for error reporting + DiagnosticPosition cbPos = getDiagnosticPosition(tree, repeatable.type); Assert.checkNonNull(cbPos); - chk.validateContainedBy(c, containedBy, cbPos); - } - - // If this annotation has a @ContainerFor, validate - Attribute.Compound containerFor = c.attribute(syms.containerForType.tsym); - if (containerFor != null) { - // get diagnositc position for error reporting - DiagnosticPosition cfPos = getDiagnosticPosition(tree, containerFor.type); - Assert.checkNonNull(cfPos); - - chk.validateContainerFor(c, containerFor, cfPos); + chk.validateRepeatable(c, repeatable, cbPos); } } else { // Check that all extended classes and interfaces @@ -3925,6 +4091,12 @@ public class Attr extends JCTree.Visitor { (c.flags() & ABSTRACT) == 0) { checkSerialVersionUID(tree, c); } + + // Correctly organize the postions of the type annotations + TypeAnnotations.organizeTypeAnnotationsBodies(this.syms, this.names, this.log, tree); + + // Check type annotations applicability rules + validateTypeAnnotations(tree); } // where /** get a diagnostic position for an attribute of Type t, or null if attribute missing */ @@ -3982,6 +4154,94 @@ public class Attr extends JCTree.Visitor { return types.capture(type); } + private void validateTypeAnnotations(JCTree tree) { + tree.accept(typeAnnotationsValidator); + } + //where + private final JCTree.Visitor typeAnnotationsValidator = + new TreeScanner() { + public void visitAnnotation(JCAnnotation tree) { + if (tree.hasTag(TYPE_ANNOTATION)) { + // TODO: It seems to WMD as if the annotation in + // parameters, in particular also the recvparam, are never + // of type JCTypeAnnotation and therefore never checked! + // Luckily this check doesn't really do anything that isn't + // also done elsewhere. + chk.validateTypeAnnotation(tree, false); + } + super.visitAnnotation(tree); + } + public void visitTypeParameter(JCTypeParameter tree) { + chk.validateTypeAnnotations(tree.annotations, true); + scan(tree.bounds); + // Don't call super. + // This is needed because above we call validateTypeAnnotation with + // false, which would forbid annotations on type parameters. + // super.visitTypeParameter(tree); + } + public void visitMethodDef(JCMethodDecl tree) { + // Static methods cannot have receiver type annotations. + // In test case FailOver15.java, the nested method getString has + // a null sym, because an unknown class is instantiated. + // I would say it's safe to skip. + if (tree.sym != null && (tree.sym.flags() & Flags.STATIC) != 0) { + if (tree.recvparam != null) { + // TODO: better error message. Is the pos good? + log.error(tree.recvparam.pos(), "annotation.type.not.applicable"); + } + } + if (tree.restype != null && tree.restype.type != null) { + validateAnnotatedType(tree.restype, tree.restype.type); + } + super.visitMethodDef(tree); + } + public void visitVarDef(final JCVariableDecl tree) { + if (tree.sym != null && tree.sym.type != null) + validateAnnotatedType(tree, tree.sym.type); + super.visitVarDef(tree); + } + public void visitTypeCast(JCTypeCast tree) { + if (tree.clazz != null && tree.clazz.type != null) + validateAnnotatedType(tree.clazz, tree.clazz.type); + super.visitTypeCast(tree); + } + public void visitTypeTest(JCInstanceOf tree) { + if (tree.clazz != null && tree.clazz.type != null) + validateAnnotatedType(tree.clazz, tree.clazz.type); + super.visitTypeTest(tree); + } + // TODO: what else do we need? + // public void visitNewClass(JCNewClass tree) { + // public void visitNewArray(JCNewArray tree) { + + /* I would want to model this after + * com.sun.tools.javac.comp.Check.Validator.visitSelectInternal(JCFieldAccess) + * and override visitSelect and visitTypeApply. + * However, we only set the annotated type in the top-level type + * of the symbol. + * Therefore, we need to override each individual location where a type + * can occur. + */ + private void validateAnnotatedType(final JCTree errtree, final Type type) { + if (type.getEnclosingType() != null && + type != type.getEnclosingType()) { + validateEnclosingAnnotatedType(errtree, type.getEnclosingType()); + } + for (Type targ : type.getTypeArguments()) { + validateAnnotatedType(errtree, targ); + } + } + private void validateEnclosingAnnotatedType(final JCTree errtree, final Type type) { + validateAnnotatedType(errtree, type); + if (type.tsym != null && + type.tsym.isStatic() && + type.getAnnotations().nonEmpty()) { + // Enclosing static classes cannot have type annotations. + log.error(errtree.pos(), "cant.annotate.static.class"); + } + } + }; + // /** @@ -4087,12 +4347,29 @@ public class Attr extends JCTree.Visitor { super.visitUnary(that); } + @Override + public void visitLambda(JCLambda that) { + super.visitLambda(that); + if (that.descriptorType == null) { + that.descriptorType = syms.unknownType; + } + if (that.targets == null) { + that.targets = List.nil(); + } + } + @Override public void visitReference(JCMemberReference that) { super.visitReference(that); if (that.sym == null) { that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol); } + if (that.descriptorType == null) { + that.descriptorType = syms.unknownType; + } + if (that.targets == null) { + that.targets = List.nil(); + } } } // diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 7db55b62c02..43283c8154f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -26,7 +26,7 @@ package com.sun.tools.javac.comp; import java.util.*; -import java.util.Set; + import javax.tools.JavaFileManager; import com.sun.tools.javac.code.*; @@ -36,7 +36,6 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; -import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Type.*; @@ -44,6 +43,8 @@ import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.ANNOTATION; @@ -100,6 +101,9 @@ public class Check { context.put(checkKey, this); names = Names.instance(context); + dfltTargetMeta = new Name[] { names.PACKAGE, names.TYPE, + names.FIELD, names.METHOD, names.CONSTRUCTOR, + names.ANNOTATION_TYPE, names.LOCAL_VARIABLE, names.PARAMETER}; log = Log.instance(context); rs = Resolve.instance(context); syms = Symtab.instance(context); @@ -571,35 +575,28 @@ public class Check { if (!tree.type.isErroneous() && (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST)) && types.isSameType(tree.expr.type, tree.clazz.type) + && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz)) && !is292targetTypeCast(tree)) { log.warning(Lint.LintCategory.CAST, tree.pos(), "redundant.cast", tree.expr.type); } } //where - private boolean is292targetTypeCast(JCTypeCast tree) { - boolean is292targetTypeCast = false; - JCExpression expr = TreeInfo.skipParens(tree.expr); - if (expr.hasTag(APPLY)) { - JCMethodInvocation apply = (JCMethodInvocation)expr; - Symbol sym = TreeInfo.symbol(apply.meth); - is292targetTypeCast = sym != null && - sym.kind == MTH && - (sym.flags() & HYPOTHETICAL) != 0; - } - return is292targetTypeCast; + private boolean is292targetTypeCast(JCTypeCast tree) { + boolean is292targetTypeCast = false; + JCExpression expr = TreeInfo.skipParens(tree.expr); + if (expr.hasTag(APPLY)) { + JCMethodInvocation apply = (JCMethodInvocation)expr; + Symbol sym = TreeInfo.symbol(apply.meth); + is292targetTypeCast = sym != null && + sym.kind == MTH && + (sym.flags() & HYPOTHETICAL) != 0; } - - - -//where - /** Is type a type variable, or a (possibly multi-dimensional) array of - * type variables? - */ - boolean isTypeVar(Type t) { - return t.hasTag(TYPEVAR) || t.hasTag(ARRAY) && isTypeVar(types.elemtype(t)); + return is292targetTypeCast; } + private static final boolean ignoreAnnotatedCasts = true; + /** Check that a type is within some bounds. * * Used in TypeApply to verify that, e.g., X in {@code V} is a valid @@ -634,25 +631,40 @@ public class Check { } } + Type checkClassOrArrayType(DiagnosticPosition pos, Type t) { + if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { + return typeTagError(pos, + diags.fragment("type.req.class.array"), + asTypeParam(t)); + } else { + return t; + } + } + /** Check that type is a class or interface type. * @param pos Position to be used for error reporting. * @param t The type to be checked. */ Type checkClassType(DiagnosticPosition pos, Type t) { - if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) + if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) { return typeTagError(pos, diags.fragment("type.req.class"), - (t.hasTag(TYPEVAR)) - ? diags.fragment("type.parameter", t) - : t); - else + asTypeParam(t)); + } else { return t; + } } + //where + private Object asTypeParam(Type t) { + return (t.hasTag(TYPEVAR)) + ? diags.fragment("type.parameter", t) + : t; + } /** Check that type is a valid qualifier for a constructor reference expression */ Type checkConstructorRefType(DiagnosticPosition pos, Type t) { - t = checkClassType(pos, t); + t = checkClassOrArrayType(pos, t); if (t.hasTag(CLASS)) { if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { log.error(pos, "abstract.cant.be.instantiated"); @@ -690,11 +702,8 @@ public class Check { * @param t The type to be checked. */ Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { - if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) { - return typeTagError(pos, - diags.fragment("type.req.class.array"), - t); - } else if (!types.isReifiable(t)) { + t = checkClassOrArrayType(pos, t); + if (!t.isErroneous() && !types.isReifiable(t)) { log.error(pos, "illegal.generic.type.for.instof"); return types.createErrorType(t); } else { @@ -840,7 +849,7 @@ public class Check { // System.out.println("actuals: " + argtypes); List formals = owntype.getParameterTypes(); Type last = useVarargs ? formals.last() : null; - if (sym.name==names.init && + if (sym.name == names.init && sym.owner == syms.enumSym) formals = formals.tail.tail; List args = argtrees; @@ -888,7 +897,6 @@ public class Check { syms.methodClass); } if (useVarargs) { - JCTree tree = env.tree; Type argtype = owntype.getParameterTypes().last(); if (!types.isReifiable(argtype) && (!allowSimplifiedVarargs || @@ -899,22 +907,13 @@ public class Check { argtype); } if (!((MethodSymbol)sym.baseSymbol()).isSignaturePolymorphic(types)) { - Type elemtype = types.elemtype(argtype); - switch (tree.getTag()) { - case APPLY: - ((JCMethodInvocation) tree).varargsElement = elemtype; - break; - case NEWCLASS: - ((JCNewClass) tree).varargsElement = elemtype; - break; - case REFERENCE: - ((JCMemberReference) tree).varargsElement = elemtype; - break; - default: - throw new AssertionError(""+tree); - } + TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype)); } } + PolyKind pkind = (sym.type.hasTag(FORALL) && + sym.type.getReturnType().containsAny(((ForAll)sym.type).tvars)) ? + PolyKind.POLY : PolyKind.STANDALONE; + TreeInfo.setPolyKind(env.tree, pkind); return owntype; } //where @@ -1055,9 +1054,12 @@ public class Check { } else mask = ConstructorFlags; } else if ((sym.owner.flags_field & INTERFACE) != 0) { - if ((flags & DEFAULT) != 0) { - mask = InterfaceDefaultMethodMask; - implicit = PUBLIC | ABSTRACT; + if ((flags & (DEFAULT | STATIC)) != 0) { + mask = InterfaceMethodMask; + implicit = PUBLIC; + if ((flags & DEFAULT) != 0) { + implicit |= ABSTRACT; + } } else { mask = implicit = InterfaceMethodFlags; } @@ -1126,6 +1128,10 @@ public class Check { ABSTRACT, PRIVATE | STATIC | DEFAULT)) && + checkDisjoint(pos, flags, + STATIC, + DEFAULT) + && checkDisjoint(pos, flags, ABSTRACT | INTERFACE, FINAL | NATIVE | SYNCHRONIZED) @@ -1316,6 +1322,11 @@ public class Check { } } + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + tree.underlyingType.accept(this); + } + /** Default visitor method: do nothing. */ @Override @@ -2236,7 +2247,7 @@ public class Check { void checkImplementations(JCClassDecl tree) { checkImplementations(tree, tree.sym, tree.sym); } -//where + //where /** Check that all methods which implement some * method in `ic' conform to the method they implement. */ @@ -2577,6 +2588,13 @@ public class Check { validateAnnotation(a, s); } + /** Check the type annotations. + */ + public void validateTypeAnnotations(List annotations, boolean isTypeParameter) { + for (JCAnnotation a : annotations) + validateTypeAnnotation(a, isTypeParameter); + } + /** Check an annotation of a symbol. */ private void validateAnnotation(JCAnnotation a, Symbol s) { @@ -2589,33 +2607,53 @@ public class Check { if (!isOverrider(s)) log.error(a.pos(), "method.does.not.override.superclass"); } + + if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { + if (s.kind != TYP) { + log.error(a.pos(), "bad.functional.intf.anno"); + } else { + try { + types.findDescriptorSymbol((TypeSymbol)s); + } catch (Types.FunctionDescriptorLookupError ex) { + log.error(a.pos(), "bad.functional.intf.anno.1", ex.getDiagnostic()); + } + } + } + } + + public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { + Assert.checkNonNull(a.type, "annotation tree hasn't been attributed yet: " + a); + validateAnnotationTree(a); + + if (!isTypeAnnotation(a, isTypeParameter)) + log.error(a.pos(), "annotation.type.not.applicable"); } /** - * Validate the proposed container 'containedBy' on the + * Validate the proposed container 'repeatable' on the * annotation type symbol 's'. Report errors at position * 'pos'. * - * @param s The (annotation)type declaration annotated with a @ContainedBy - * @param containedBy the @ContainedBy on 's' + * @param s The (annotation)type declaration annotated with a @Repeatable + * @param repeatable the @Repeatable on 's' * @param pos where to report errors */ - public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) { - Assert.check(types.isSameType(containedBy.type, syms.containedByType)); + public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) { + Assert.check(types.isSameType(repeatable.type, syms.repeatableType)); Type t = null; - List> l = containedBy.values; + List> l = repeatable.values; if (!l.isEmpty()) { Assert.check(l.head.fst.name == names.value); t = ((Attribute.Class)l.head.snd).getValue(); } if (t == null) { - log.error(pos, "invalid.container.wrong.containedby", s, containedBy); + // errors should already have been reported during Annotate return; } - validateHasContainerFor(t.tsym, s, pos); + validateValue(t.tsym, s, pos); validateRetention(t.tsym, s, pos); validateDocumented(t.tsym, s, pos); validateInherited(t.tsym, s, pos); @@ -2623,79 +2661,18 @@ public class Check { validateDefault(t.tsym, s, pos); } - /** - * Validate the proposed container 'containerFor' on the - * annotation type symbol 's'. Report errors at position - * 'pos'. - * - * @param s The (annotation)type declaration annotated with a @ContainerFor - * @param containerFor the @ContainedFor on 's' - * @param pos where to report errors - */ - public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) { - Assert.check(types.isSameType(containerFor.type, syms.containerForType)); - - Type t = null; - List> l = containerFor.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); + private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { + Scope.Entry e = container.members().lookup(names.value); + if (e.scope != null && e.sym.kind == MTH) { + MethodSymbol m = (MethodSymbol) e.sym; + Type ret = m.getReturnType(); + if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) { + log.error(pos, "invalid.repeatable.annotation.value.return", + container, ret, types.makeArrayType(contained.type)); + } + } else { + log.error(pos, "invalid.repeatable.annotation.no.value", container); } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containerfor", s, containerFor); - return; - } - - validateHasContainedBy(t.tsym, s, pos); - } - - private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { - Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym); - - if (containedBy == null) { - log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym); - return; - } - - Type t = null; - List> l = containedBy.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); - } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containedby", container, contained); - return; - } - - if (!types.isSameType(t, contained.type)) - log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained); - } - - private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { - Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym); - - if (containerFor == null) { - log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym); - return; - } - - Type t = null; - List> l = containerFor.values; - if (!l.isEmpty()) { - Assert.check(l.head.fst.name == names.value); - t = ((Attribute.Class)l.head.snd).getValue(); - } - - if (t == null) { - log.error(pos, "invalid.container.wrong.containerfor", container, contained); - return; - } - - if (!types.isSameType(t, contained.type)) - log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained); } private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) { @@ -2715,7 +2692,7 @@ public class Check { } } if (error ) { - log.error(pos, "invalid.containedby.annotation.retention", + log.error(pos, "invalid.repeatable.annotation.retention", container, containerRetention, contained, containedRetention); } @@ -2724,7 +2701,7 @@ public class Check { private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) { if (contained.attribute(syms.documentedType.tsym) != null) { if (container.attribute(syms.documentedType.tsym) == null) { - log.error(pos, "invalid.containedby.annotation.not.documented", container, contained); + log.error(pos, "invalid.repeatable.annotation.not.documented", container, contained); } } } @@ -2732,7 +2709,7 @@ public class Check { private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) { if (contained.attribute(syms.inheritedType.tsym) != null) { if (container.attribute(syms.inheritedType.tsym) == null) { - log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained); + log.error(pos, "invalid.repeatable.annotation.not.inherited", container, contained); } } } @@ -2752,7 +2729,7 @@ public class Check { // contained has target, but container has not, error Attribute.Array containerTarget = getAttributeTargetAttribute(container); if (containerTarget == null) { - log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); + log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); return; } @@ -2775,7 +2752,7 @@ public class Check { } if (!isTargetSubset(containedTargets, containerTargets)) { - log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); + log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained); } } @@ -2809,7 +2786,7 @@ public class Check { elm.kind == Kinds.MTH && ((MethodSymbol)elm).defaultValue == null) { log.error(pos, - "invalid.containedby.annotation.elem.nondefault", + "invalid.repeatable.annotation.elem.nondefault", container, elm); } @@ -2834,45 +2811,90 @@ public class Check { return false; } + /** Is the annotation applicable to type annotations? */ + protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) { + Attribute.Compound atTarget = + a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); + if (atTarget == null) { + // An annotation without @Target is not a type annotation. + return false; + } + + Attribute atValue = atTarget.member(names.value); + if (!(atValue instanceof Attribute.Array)) { + return false; // error recovery + } + + Attribute.Array arr = (Attribute.Array) atValue; + for (Attribute app : arr.values) { + if (!(app instanceof Attribute.Enum)) { + return false; // recovery + } + Attribute.Enum e = (Attribute.Enum) app; + + if (e.value.name == names.TYPE_USE) + return true; + else if (isTypeParameter && e.value.name == names.TYPE_PARAMETER) + return true; + } + return false; + } + /** Is the annotation applicable to the symbol? */ boolean annotationApplicable(JCAnnotation a, Symbol s) { Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); + Name[] targets; + if (arr == null) { - return true; + targets = defaultTargetMetaInfo(a, s); + } else { + // TODO: can we optimize this? + targets = new Name[arr.values.length]; + for (int i=0; inil(), new StructuralStuckChecker()); + return true; + case CHECK: + if (stuckVars.nonEmpty()) { + return false; + } else { + dt.check(resultInfo, stuckVars, basicCompleter); + return true; + } + default: + throw new AssertionError("Bad mode"); + } + } + + /** + * Structural checker for stuck expressions + */ + class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter { + + ResultInfo resultInfo; + + public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { + this.resultInfo = resultInfo; + dt.tree.accept(this); + dt.speculativeCache.put(msym, stuckTree, phase); + return Type.noType; + } + + @Override + public void visitLambda(JCLambda tree) { + Check.CheckContext checkContext = resultInfo.checkContext; + Type pt = resultInfo.pt; + if (inferenceContext.inferencevars.contains(pt)) { + //ok + return; + } else { + //must be a functional descriptor + try { + Type desc = types.findDescriptorType(pt); + if (desc.getParameterTypes().length() != tree.params.length()) { + checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); + } + } catch (Types.FunctionDescriptorLookupError ex) { + checkContext.report(null, ex.getDiagnostic()); + } + } + } + + @Override + public void visitNewClass(JCNewClass tree) { + //do nothing + } + + @Override + public void visitApply(JCMethodInvocation tree) { + //do nothing + } + + @Override + public void visitReference(JCMemberReference tree) { + Check.CheckContext checkContext = resultInfo.checkContext; + Type pt = resultInfo.pt; + if (inferenceContext.inferencevars.contains(pt)) { + //ok + return; + } else { + try { + //TODO: we should speculative determine if there's a match + //based on arity - if yes, method is applicable. + types.findDescriptorType(pt); + } catch (Types.FunctionDescriptorLookupError ex) { + checkContext.report(null, ex.getDiagnostic()); + } + } } - dt.check(resultInfo); } } } @@ -624,12 +697,12 @@ public class DeferredAttr extends JCTree.Visitor { if (inferenceContext.inferenceVars().contains(pt)) { stuckVars.add(pt); } - if (!types.isFunctionalInterface(pt.tsym)) { + if (!types.isFunctionalInterface(pt)) { return; } Type descType = types.findDescriptorType(pt); List freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); - if (!TreeInfo.isExplicitLambda(tree) && + if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT && freeArgVars.nonEmpty()) { stuckVars.addAll(freeArgVars); } @@ -643,7 +716,7 @@ public class DeferredAttr extends JCTree.Visitor { stuckVars.add(pt); return; } - if (!types.isFunctionalInterface(pt.tsym)) { + if (!types.isFunctionalInterface(pt)) { return; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java index ccf7a82badd..1165a151aa2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -131,7 +131,11 @@ public class Enter extends JCTree.Visitor { predefClassDef = make.ClassDef( make.Modifiers(PUBLIC), - syms.predefClass.name, null, null, null, null); + syms.predefClass.name, + List.nil(), + null, + List.nil(), + List.nil()); predefClassDef.sym = syms.predefClass; todo = Todo.instance(context); fileManager = context.get(JavaFileManager.class); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java index 21863e7f075..3942f22b2a1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -35,6 +35,7 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.comp.Resolve; import com.sun.tools.javac.tree.JCTree.*; import static com.sun.tools.javac.code.Flags.*; @@ -2175,6 +2176,11 @@ public class Flow { unrefdResources.remove(sym); } + public void visitAnnotatedType(JCAnnotatedType tree) { + // annotations don't get scanned + tree.underlyingType.accept(this); + } + public void visitTopLevel(JCCompilationUnit tree) { // Do nothing for TopLevel since each class is visited individually } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java index 3c26e0d480a..c6e1894f306 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -66,6 +66,9 @@ public class Infer { Log log; JCDiagnostic.Factory diags; + /** Should we inject return-type constraints earlier? */ + boolean allowEarlyReturnConstraints; + public static Infer instance(Context context) { Infer instance = context.get(inferKey); if (instance == null) @@ -83,6 +86,7 @@ public class Infer { chk = Check.instance(context); diags = JCDiagnostic.Factory.instance(context); inferenceException = new InferenceException(diags); + allowEarlyReturnConstraints = Source.instance(context).allowEarlyReturnConstraints(); } /** @@ -188,19 +192,6 @@ public class Infer { MethodType mtype, Attr.ResultInfo resultInfo, Warner warn) throws InferenceException { - Type to = resultInfo.pt; - if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { - to = mtype.getReturnType().isPrimitiveOrVoid() ? - mtype.getReturnType() : syms.objectType; - } - Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types); - if (!types.isSubtype(qtype1, - qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) { - throw inferenceException - .setMessage("infer.no.conforming.instance.exists", - inferenceContext.restvars(), mtype.getReturnType(), to); - } - while (true) { boolean stuck = true; for (Type t : inferenceContext.undetvars) { @@ -283,6 +274,11 @@ public class Infer { try { methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn); + if (resultInfo != null && allowEarlyReturnConstraints && + !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { + generateReturnConstraints(mt, inferenceContext, resultInfo); + } + deferredAttrContext.complete(); // minimize as yet undetermined type variables @@ -298,6 +294,9 @@ public class Infer { if (!restvars.isEmpty()) { if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { + if (!allowEarlyReturnConstraints) { + generateReturnConstraints(mt, inferenceContext, resultInfo); + } instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn); checkWithinBounds(inferenceContext, warn); mt = (MethodType)inferenceContext.asInstType(mt, types); @@ -313,6 +312,25 @@ public class Infer { inferenceContext.notifyChange(types); } } + //where + void generateReturnConstraints(Type mt, InferenceContext inferenceContext, Attr.ResultInfo resultInfo) { + if (resultInfo != null) { + Type to = resultInfo.pt; + if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { + to = mt.getReturnType().isPrimitiveOrVoid() ? + mt.getReturnType() : syms.objectType; + } + Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types); + Warner retWarn = new Warner(); + if (!resultInfo.checkContext.compatible(qtype1, qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to, retWarn) || + //unchecked conversion is not allowed + retWarn.hasLint(Lint.LintCategory.UNCHECKED)) { + throw inferenceException + .setMessage("infer.no.conforming.instance.exists", + inferenceContext.restvars(), mt.getReturnType(), to); + } + } + } /** check that type parameters are within their bounds. */ @@ -461,52 +479,40 @@ public class Infer { Type formalInterface = funcInterface.tsym.type; InferenceContext funcInterfaceContext = new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false); - if (paramTypes != null) { - //get constraints from explicit params (this is done by - //checking that explicit param types are equal to the ones - //in the functional interface descriptors) - List descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes(); - if (descParameterTypes.size() != paramTypes.size()) { - checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda")); + Assert.check(paramTypes != null); + //get constraints from explicit params (this is done by + //checking that explicit param types are equal to the ones + //in the functional interface descriptors) + List descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes(); + if (descParameterTypes.size() != paramTypes.size()) { + checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda")); + return types.createErrorType(funcInterface); + } + for (Type p : descParameterTypes) { + if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) { + checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); return types.createErrorType(funcInterface); } - for (Type p : descParameterTypes) { - if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) { - checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); - return types.createErrorType(funcInterface); - } - paramTypes = paramTypes.tail; - } - for (Type t : funcInterfaceContext.undetvars) { - UndetVar uv = (UndetVar)t; - minimizeInst(uv, types.noWarnings); - if (uv.inst == null && - Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) { - maximizeInst(uv, types.noWarnings); - } - } - - formalInterface = funcInterfaceContext.asInstType(formalInterface, types); + paramTypes = paramTypes.tail; } - ListBuffer typeargs = ListBuffer.lb(); List actualTypeargs = funcInterface.getTypeArguments(); - //for remaining uninferred type-vars in the functional interface type, - //simply replace the wildcards with its bound - for (Type t : formalInterface.getTypeArguments()) { - if (actualTypeargs.head.hasTag(WILDCARD)) { - WildcardType wt = (WildcardType)actualTypeargs.head; - typeargs.append(wt.type); - } else { - typeargs.append(actualTypeargs.head); + for (Type t : funcInterfaceContext.undetvars) { + UndetVar uv = (UndetVar)t; + minimizeInst(uv, types.noWarnings); + if (uv.inst == null && + Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) { + maximizeInst(uv, types.noWarnings); + } + if (uv.inst == null) { + uv.inst = actualTypeargs.head; } actualTypeargs = actualTypeargs.tail; } - Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList()); + Type owntype = funcInterfaceContext.asInstType(formalInterface, types); if (!chk.checkValidGenericType(owntype)) { //if the inferred functional interface type is not well-formed, //or if it's not a subtype of the original target, issue an error checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); - return types.createErrorType(funcInterface); } return owntype; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index 6ad3da8ddae..767da17d60d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -253,7 +253,7 @@ public class LambdaToMethod extends TreeTranslator { int refKind = referenceKind(sym); //convert to an invokedynamic call - result = makeMetaFactoryIndyCall(tree, tree.targetType, refKind, sym, indy_args); + result = makeMetaFactoryIndyCall(tree, refKind, sym, indy_args); } private JCIdent makeThis(Type type, Symbol owner) { @@ -302,6 +302,7 @@ public class LambdaToMethod extends TreeTranslator { case UNBOUND: /** Type :: instMethod */ case STATIC: /** Type :: staticMethod */ case TOPLEVEL: /** Top level :: new */ + case ARRAY_CTOR: /** ArrayType :: new */ init = null; break; @@ -313,7 +314,7 @@ public class LambdaToMethod extends TreeTranslator { //build a sam instance using an indy call to the meta-factory - result = makeMetaFactoryIndyCall(tree, tree.targetType, localContext.referenceKind(), refSym, indy_args); + result = makeMetaFactoryIndyCall(tree, localContext.referenceKind(), refSym, indy_args); } /** @@ -502,19 +503,6 @@ public class LambdaToMethod extends TreeTranslator { // - private MethodSymbol makeSamDescriptor(Type targetType) { - return (MethodSymbol)types.findDescriptorSymbol(targetType.tsym); - } - - private Type makeFunctionalDescriptorType(Type targetType, MethodSymbol samDescriptor, boolean erased) { - Type descType = types.memberType(targetType, samDescriptor); - return erased ? types.erasure(descType) : descType; - } - - private Type makeFunctionalDescriptorType(Type targetType, boolean erased) { - return makeFunctionalDescriptorType(targetType, makeSamDescriptor(targetType), erased); - } - /** * Generate an adapter method "bridge" for a method reference which cannot * be used directly. @@ -645,24 +633,33 @@ public class LambdaToMethod extends TreeTranslator { * to the first bridge synthetic parameter */ private JCExpression bridgeExpressionNew() { - JCExpression encl = null; - switch (tree.kind) { - case UNBOUND: - case IMPLICIT_INNER: - encl = make.Ident(params.first()); - } + if (tree.kind == ReferenceKind.ARRAY_CTOR) { + //create the array creation expression + JCNewArray newArr = make.NewArray(make.Type(types.elemtype(tree.getQualifierExpression().type)), + List.of(make.Ident(params.first())), + null); + newArr.type = tree.getQualifierExpression().type; + return newArr; + } else { + JCExpression encl = null; + switch (tree.kind) { + case UNBOUND: + case IMPLICIT_INNER: + encl = make.Ident(params.first()); + } - //create the instance creation expression - JCNewClass newClass = make.NewClass(encl, - List.nil(), - make.Type(tree.getQualifierExpression().type), - convertArgs(tree.sym, args.toList(), tree.varargsElement), - null); - newClass.constructor = tree.sym; - newClass.constructorType = tree.sym.erasure(types); - newClass.type = tree.getQualifierExpression().type; - setVarargsIfNeeded(newClass, tree.varargsElement); - return newClass; + //create the instance creation expression + JCNewClass newClass = make.NewClass(encl, + List.nil(), + make.Type(tree.getQualifierExpression().type), + convertArgs(tree.sym, args.toList(), tree.varargsElement), + null); + newClass.constructor = tree.sym; + newClass.constructorType = tree.sym.erasure(types); + newClass.type = tree.getQualifierExpression().type; + setVarargsIfNeeded(newClass, tree.varargsElement); + return newClass; + } } private VarSymbol addParameter(String name, Type p, boolean genArg) { @@ -688,12 +685,12 @@ public class LambdaToMethod extends TreeTranslator { /** * Generate an indy method call to the meta factory */ - private JCExpression makeMetaFactoryIndyCall(JCExpression tree, Type targetType, int refKind, Symbol refSym, List indy_args) { + private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, int refKind, Symbol refSym, List indy_args) { //determine the static bsm args - Type mtype = makeFunctionalDescriptorType(targetType, true); + Type mtype = types.erasure(tree.descriptorType); + MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym); List staticArgs = List.of( - new Pool.MethodHandle(ClassFile.REF_invokeInterface, - types.findDescriptorSymbol(targetType.tsym), types), + new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(tree.type.tsym), types), new Pool.MethodHandle(refKind, refSym, types), new MethodType(mtype.getParameterTypes(), mtype.getReturnType(), @@ -862,8 +859,8 @@ public class LambdaToMethod extends TreeTranslator { finally { frameStack = prevStack; } - if (frameStack.nonEmpty() && enclosingLambda() != null) { - // Any class defined within a lambda is an implicit 'this' reference + if (!tree.sym.isStatic() && frameStack.nonEmpty() && enclosingLambda() != null) { + // Any (non-static) class defined within a lambda is an implicit 'this' reference // because its constructor will reference the enclosing class ((LambdaTranslationContext) context()).addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS); } @@ -997,6 +994,11 @@ public class LambdaToMethod extends TreeTranslator { * (required to skip synthetic lambda symbols) */ private Symbol owner() { + return owner(false); + } + + @SuppressWarnings("fallthrough") + private Symbol owner(boolean skipLambda) { List frameStack2 = frameStack; while (frameStack2.nonEmpty()) { switch (frameStack2.head.tree.getTag()) { @@ -1015,7 +1017,8 @@ public class LambdaToMethod extends TreeTranslator { case METHODDEF: return ((JCMethodDecl)frameStack2.head.tree).sym; case LAMBDA: - return ((LambdaTranslationContext)contextMap.get(frameStack2.head.tree)).translatedSym; + if (!skipLambda) + return ((LambdaTranslationContext)contextMap.get(frameStack2.head.tree)).translatedSym; default: frameStack2 = frameStack2.tail; } @@ -1155,7 +1158,7 @@ public class LambdaToMethod extends TreeTranslator { * This class is used to store important information regarding translation of * lambda expression/method references (see subclasses). */ - private abstract class TranslationContext { + private abstract class TranslationContext { /** the underlying (untranslated) tree */ T tree; @@ -1314,12 +1317,13 @@ public class LambdaToMethod extends TreeTranslator { } Type enclosingType() { - //local inner classes defined inside a lambda are always non-static - return owner.enclClass().type; + return owner.isStatic() ? + Type.noType : + owner.enclClass().type; } Type generatedLambdaSig() { - return types.erasure(types.findDescriptorType(tree.targetType)); + return types.erasure(tree.descriptorType); } } @@ -1375,7 +1379,7 @@ public class LambdaToMethod extends TreeTranslator { } Type bridgedRefSig() { - return types.erasure(types.findDescriptorSymbol(tree.targetType.tsym).type); + return types.erasure(types.findDescriptorSymbol(tree.targets.head).type); } } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index 4005a25887a..fb5202dffcb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -570,10 +570,19 @@ public class Lower extends TreeTranslator { * @param flags The class symbol's flags * @param owner The class symbol's owner */ - ClassSymbol makeEmptyClass(long flags, ClassSymbol owner) { + JCClassDecl makeEmptyClass(long flags, ClassSymbol owner) { + return makeEmptyClass(flags, owner, null, true); + } + + JCClassDecl makeEmptyClass(long flags, ClassSymbol owner, Name flatname, + boolean addToDefs) { // Create class symbol. ClassSymbol c = reader.defineClass(names.empty, owner); - c.flatname = chk.localClassName(c); + if (flatname != null) { + c.flatname = flatname; + } else { + c.flatname = chk.localClassName(c); + } c.sourcefile = owner.sourcefile; c.completer = null; c.members_field = new Scope(c); @@ -597,9 +606,8 @@ public class Lower extends TreeTranslator { cdef.type = c.type; // Append class definition tree to owner's definitions. - odef.defs = odef.defs.prepend(cdef); - - return c; + if (addToDefs) odef.defs = odef.defs.prepend(cdef); + return cdef; } /************************************************************************** @@ -706,7 +714,7 @@ public class Lower extends TreeTranslator { * and synthethise a class (with makeEmptyClass) if one is not available. * However, there is a small possibility that an existing class will not * be generated as expected if it is inside a conditional with a constant - * expression. If that is found to be the case, create an empty class here. + * expression. If that is found to be the case, create an empty class tree here. */ private void checkAccessConstructorTags() { for (List l = accessConstrTags; l.nonEmpty(); l = l.tail) { @@ -714,14 +722,10 @@ public class Lower extends TreeTranslator { if (isTranslatedClassAvailable(c)) continue; // Create class definition tree. - JCClassDecl cdef = make.ClassDef( - make.Modifiers(STATIC | SYNTHETIC), names.empty, - List.nil(), - null, List.nil(), List.nil()); - cdef.sym = c; - cdef.type = c.type; - // add it to the list of classes to be generated - translated.append(cdef); + JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC, + c.outermostClass(), c.flatname, false); + swapAccessConstructorTag(c, cdec.sym); + translated.append(cdec); } } // where @@ -735,6 +739,19 @@ public class Lower extends TreeTranslator { return false; } + void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) { + for (MethodSymbol methodSymbol : accessConstrs.values()) { + Assert.check(methodSymbol.type.hasTag(METHOD)); + MethodType oldMethodType = + (MethodType)methodSymbol.type; + if (oldMethodType.argtypes.head.tsym == oldCTag) + methodSymbol.type = + types.createMethodTypeWithParameters(oldMethodType, + oldMethodType.getParameterTypes().tail + .prepend(newCTag.erasure(types))); + } + } + /************************************************************************** * Access methods *************************************************************************/ @@ -1211,7 +1228,7 @@ public class Lower extends TreeTranslator { "1"); ClassSymbol ctag = chk.compiled.get(flatname); if (ctag == null) - ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass); + ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym; // keep a record of all tags, to verify that all are generated as required accessConstrTags = accessConstrTags.prepend(ctag); return ctag; @@ -1778,7 +1795,7 @@ public class Lower extends TreeTranslator { if (e.sym.kind == TYP && e.sym.name == names.empty && (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym; - return makeEmptyClass(STATIC | SYNTHETIC, clazz); + return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym; } /** Return symbol for "class$" method. If there is no method definition @@ -2288,7 +2305,7 @@ public class Lower extends TreeTranslator { return tree.packageAnnotations.nonEmpty(); case NONEMPTY: for (Attribute.Compound a : - tree.packge.annotations.getAttributes()) { + tree.packge.annotations.getDeclarationAttributes()) { Attribute.RetentionPolicy p = types.getRetention(a); if (p != Attribute.RetentionPolicy.SOURCE) return true; @@ -2685,6 +2702,13 @@ public class Lower extends TreeTranslator { result = tree; } + public void visitAnnotatedType(JCAnnotatedType tree) { + // No need to retain type annotations any longer. + // tree.annotations = translate(tree.annotations); + tree.underlyingType = translate(tree.underlyingType); + result = tree.underlyingType; + } + public void visitTypeCast(JCTypeCast tree) { tree.clazz = translate(tree.clazz); if (tree.type.isPrimitive() != tree.expr.type.isPrimitive()) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java index c290f8c71be..407a49f67c3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,19 @@ package com.sun.tools.javac.comp; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Set; + +import javax.lang.model.type.TypeKind; import javax.tools.JavaFileObject; import com.sun.tools.javac.code.*; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; -import com.sun.tools.javac.util.List; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Symbol.*; @@ -345,12 +349,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer { * @param params The method's value parameters. * @param res The method's result type, * null if it is a constructor. + * @param recvparam The method's receiver parameter, + * null if none given; TODO: or already set here? * @param thrown The method's thrown exceptions. * @param env The method's (local) environment. */ Type signature(List typarams, List params, JCTree res, + JCVariableDecl recvparam, List thrown, Env env) { @@ -368,6 +375,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer { // Attribute result type, if one is given. Type restype = res == null ? syms.voidType : attr.attribType(res, env); + // Attribute receiver type, if one is given. + Type recvtype; + if (recvparam!=null) { + memberEnter(recvparam, env); + recvtype = recvparam.vartype.type; + } else { + recvtype = null; + } + // Attribute thrown exceptions. ListBuffer thrownbuf = new ListBuffer(); for (List l = thrown; l.nonEmpty(); l = l.tail) { @@ -376,10 +392,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer { exc = chk.checkClassType(l.head.pos(), exc); thrownbuf.append(exc); } - Type mtype = new MethodType(argbuf.toList(), + MethodType mtype = new MethodType(argbuf.toList(), restype, thrownbuf.toList(), syms.methodClass); + mtype.recvtype = recvtype; + return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype); } @@ -573,7 +591,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { try { // Compute the method type m.type = signature(tree.typarams, tree.params, - tree.restype, tree.thrown, + tree.restype, tree.recvparam, + tree.thrown, localEnv); } finally { chk.setDeferredLintHandler(prevLintHandler); @@ -597,6 +616,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer { enclScope.enter(m); } annotateLater(tree.mods.annotations, localEnv, m); + // Visit the signature of the method. Note that + // TypeAnnotate doesn't descend into the body. + typeAnnotate(tree, localEnv, m); + if (tree.defaultValue != null) annotateDefaultValueLater(tree.defaultValue, localEnv, m); } @@ -642,7 +665,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { //(a plain array type) with the more precise VarargsType --- we need //to do it this way because varargs is represented in the tree as a modifier //on the parameter declaration, and not as a distinct type of array node. - ArrayType atype = (ArrayType)tree.vartype.type; + ArrayType atype = (ArrayType)tree.vartype.type.unannotatedType(); tree.vartype.type = atype.makeVarargs(); } Scope enclScope = enter.enterScope(env); @@ -665,6 +688,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { enclScope.enter(v); } annotateLater(tree.mods.annotations, localEnv, v); + typeAnnotate(tree.vartype, env, tree.sym); + annotate.flush(); v.pos = tree.pos; } @@ -759,7 +784,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { log.error(annotations.head.pos, "already.annotated", kindName(s), s); - enterAnnotations(annotations, localEnv, s); + actualEnterAnnotations(annotations, localEnv, s); } finally { log.useSource(prev); } @@ -781,7 +806,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } /** Enter a set of annotations. */ - private void enterAnnotations(List annotations, + private void actualEnterAnnotations(List annotations, Env env, Symbol s) { Map> annotated = @@ -817,11 +842,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer { && s.owner.kind != MTH && types.isSameType(c.type, syms.deprecatedType)) { s.flags_field |= Flags.DEPRECATED; - } + } } - s.annotations.setAttributesWithCompletion( - annotate.new AnnotateRepeatedContext(env, annotated, pos, log)); + s.annotations.setDeclarationAttributesWithCompletion( + annotate.new AnnotateRepeatedContext(env, annotated, pos, log, false)); } /** Queue processing of an attribute default value. */ @@ -900,6 +925,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer { // create an environment for evaluating the base clauses Env baseEnv = baseEnv(tree, env); + if (tree.extending != null) + typeAnnotate(tree.extending, baseEnv, sym); + for (JCExpression impl : tree.implementing) + typeAnnotate(impl, baseEnv, sym); + annotate.flush(); + // Determine supertype. Type supertype = (tree.extending != null) @@ -969,10 +1000,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer { if (hasDeprecatedAnnotation(tree.mods.annotations)) c.flags_field |= DEPRECATED; annotateLater(tree.mods.annotations, baseEnv, c); + // class type parameters use baseEnv but everything uses env chk.checkNonCyclicDecl(tree); attr.attribTypeVariables(tree.typarams, baseEnv); + // Do this here, where we have the symbol. + for (JCTypeParameter tp : tree.typarams) + typeAnnotate(tp, baseEnv, sym); + annotate.flush(); // Add default constructor if needed. if ((c.flags() & INTERFACE) == 0 && @@ -1050,12 +1086,120 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } finally { isFirst = true; } + } + annotate.afterRepeated(TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, tree)); + } - // commit pending annotations - annotate.flush(); + private void actualEnterTypeAnnotations(final List annotations, + final Env env, + final Symbol s) { + Map> annotated = + new LinkedHashMap>(); + Map pos = + new HashMap(); + + for (List al = annotations; !al.isEmpty(); al = al.tail) { + JCAnnotation a = al.head; + Attribute.TypeCompound tc = annotate.enterTypeAnnotation(a, + syms.annotationType, + env); + if (tc == null) { + continue; + } + + if (annotated.containsKey(a.type.tsym)) { + if (source.allowRepeatedAnnotations()) { + ListBuffer l = annotated.get(a.type.tsym); + l = l.append(tc); + annotated.put(a.type.tsym, l); + pos.put(tc, a.pos()); + } else { + log.error(a.pos(), "duplicate.annotation"); + } + } else { + annotated.put(a.type.tsym, ListBuffer.of(tc)); + pos.put(tc, a.pos()); + } + } + + s.annotations.appendTypeAttributesWithCompletion( + annotate.new AnnotateRepeatedContext(env, annotated, pos, log, true)); + } + + public void typeAnnotate(final JCTree tree, final Env env, final Symbol sym) { + tree.accept(new TypeAnnotate(env, sym)); + } + + /** + * We need to use a TreeScanner, because it is not enough to visit the top-level + * annotations. We also need to visit type arguments, etc. + */ + private class TypeAnnotate extends TreeScanner { + private Env env; + private Symbol sym; + + public TypeAnnotate(final Env env, final Symbol sym) { + this.env = env; + this.sym = sym; + } + + void annotateTypeLater(final List annotations) { + if (annotations.isEmpty()) { + return; + } + + annotate.normal(new Annotate.Annotator() { + @Override + public String toString() { + return "type annotate " + annotations + " onto " + sym + " in " + sym.owner; + } + @Override + public void enterAnnotation() { + JavaFileObject prev = log.useSource(env.toplevel.sourcefile); + try { + actualEnterTypeAnnotations(annotations, env, sym); + } finally { + log.useSource(prev); + } + } + }); + } + + @Override + public void visitAnnotatedType(final JCAnnotatedType tree) { + annotateTypeLater(tree.annotations); + super.visitAnnotatedType(tree); + } + + @Override + public void visitTypeParameter(final JCTypeParameter tree) { + annotateTypeLater(tree.annotations); + super.visitTypeParameter(tree); + } + + @Override + public void visitNewArray(final JCNewArray tree) { + annotateTypeLater(tree.annotations); + for (List dimAnnos : tree.dimAnnotations) + annotateTypeLater(dimAnnos); + super.visitNewArray(tree); + } + + @Override + public void visitMethodDef(final JCMethodDecl tree) { + scan(tree.mods); + scan(tree.restype); + scan(tree.typarams); + scan(tree.recvparam); + scan(tree.params); + scan(tree.thrown); + scan(tree.defaultValue); + // Do not annotate the body, just the signature. + // scan(tree.body); } } + private Env baseEnv(JCClassDecl tree, Env env) { Scope baseScope = new Scope(tree.sym); //import already entered local classes into base scope diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index 4b6cab1bf0e..08cc94f372f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -41,6 +41,7 @@ import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -54,7 +55,6 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; -import java.util.Set; import javax.lang.model.element.ElementVisitor; @@ -92,6 +92,7 @@ public class Resolve { public final boolean varargsEnabled; // = source.allowVarargs(); public final boolean allowMethodHandles; public final boolean allowDefaultMethods; + public final boolean allowStructuralMostSpecific; private final boolean debugResolve; final EnumSet verboseResolutionMode; @@ -127,6 +128,7 @@ public class Resolve { Target target = Target.instance(context); allowMethodHandles = target.hasMethodHandles(); allowDefaultMethods = source.allowDefaultMethods(); + allowStructuralMostSpecific = source.allowStructuralMostSpecific(); polymorphicSignatureScope = new Scope(syms.noSymbol); inapplicableMethodException = new InapplicableMethodException(diags); @@ -693,7 +695,7 @@ public class Resolve { if (varargsFormal == null && argtypes.size() != formals.size()) { - report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args + reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args } while (argtypes.nonEmpty() && formals.head != varargsFormal) { @@ -704,7 +706,7 @@ public class Resolve { } if (formals.head != varargsFormal) { - report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args + reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args } if (useVarargs) { @@ -721,7 +723,7 @@ public class Resolve { } } - private void report(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { + private void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { boolean inferDiag = inferenceContext != infer.emptyContext; InapplicableMethodException ex = inferDiag ? infer.inferenceException : inapplicableMethodException; @@ -745,7 +747,7 @@ public class Resolve { } else { if (!isAccessible(env, t)) { Symbol location = env.enclClass.sym; - report(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location); + reportMC(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location); } } } @@ -758,7 +760,7 @@ public class Resolve { @Override public void report(DiagnosticPosition pos, JCDiagnostic details) { - report(methodDiag, deferredAttrContext.inferenceContext, details); + reportMC(methodDiag, deferredAttrContext.inferenceContext, details); } }; return new MethodResultInfo(to, checkContext); @@ -835,6 +837,213 @@ public class Resolve { } } + /** + * Most specific method applicability routine. Given a list of actual types A, + * a list of formal types F1, and a list of formal types F2, the routine determines + * as to whether the types in F1 can be considered more specific than those in F2 w.r.t. + * argument types A. + */ + class MostSpecificCheck implements MethodCheck { + + boolean strict; + List actuals; + + MostSpecificCheck(boolean strict, List actuals) { + this.strict = strict; + this.actuals = actuals; + } + + @Override + public void argumentsAcceptable(final Env env, + DeferredAttrContext deferredAttrContext, + List formals1, + List formals2, + Warner warn) { + formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired()); + while (formals2.nonEmpty()) { + ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head); + mresult.check(null, formals1.head); + formals1 = formals1.tail; + formals2 = formals2.tail; + actuals = actuals.isEmpty() ? actuals : actuals.tail; + } + } + + /** + * Create a method check context to be used during the most specific applicability check + */ + ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext, + Warner rsWarner, Type actual) { + return attr.new ResultInfo(Kinds.VAL, to, + new MostSpecificCheckContext(strict, deferredAttrContext, rsWarner, actual)); + } + + /** + * Subclass of method check context class that implements most specific + * method conversion. If the actual type under analysis is a deferred type + * a full blown structural analysis is carried out. + */ + class MostSpecificCheckContext extends MethodCheckContext { + + Type actual; + + public MostSpecificCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) { + super(strict, deferredAttrContext, rsWarner); + this.actual = actual; + } + + public boolean compatible(Type found, Type req, Warner warn) { + if (!allowStructuralMostSpecific || actual == null) { + return super.compatible(found, req, warn); + } else { + switch (actual.getTag()) { + case DEFERRED: + DeferredType dt = (DeferredType) actual; + DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase); + return (e == null || e.speculativeTree == deferredAttr.stuckTree) + ? false : mostSpecific(found, req, e.speculativeTree, warn); + default: + return standaloneMostSpecific(found, req, actual, warn); + } + } + } + + private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) { + MostSpecificChecker msc = new MostSpecificChecker(t, s, warn); + msc.scan(tree); + return msc.result; + } + + boolean polyMostSpecific(Type t1, Type t2, Warner warn) { + return (!t1.isPrimitive() && t2.isPrimitive()) + ? true : super.compatible(t1, t2, warn); + } + + boolean standaloneMostSpecific(Type t1, Type t2, Type exprType, Warner warn) { + return (exprType.isPrimitive() == t1.isPrimitive() + && exprType.isPrimitive() != t2.isPrimitive()) + ? true : super.compatible(t1, t2, warn); + } + + /** + * Structural checker for most specific. + */ + class MostSpecificChecker extends DeferredAttr.PolyScanner { + + final Type t; + final Type s; + final Warner warn; + boolean result; + + MostSpecificChecker(Type t, Type s, Warner warn) { + this.t = t; + this.s = s; + this.warn = warn; + result = true; + } + + @Override + void skip(JCTree tree) { + result &= standaloneMostSpecific(t, s, tree.type, warn); + } + + @Override + public void visitConditional(JCConditional tree) { + if (tree.polyKind == PolyKind.STANDALONE) { + result &= standaloneMostSpecific(t, s, tree.type, warn); + } else { + super.visitConditional(tree); + } + } + + @Override + public void visitApply(JCMethodInvocation tree) { + result &= (tree.polyKind == PolyKind.STANDALONE) + ? standaloneMostSpecific(t, s, tree.type, warn) + : polyMostSpecific(t, s, warn); + } + + @Override + public void visitNewClass(JCNewClass tree) { + result &= (tree.polyKind == PolyKind.STANDALONE) + ? standaloneMostSpecific(t, s, tree.type, warn) + : polyMostSpecific(t, s, warn); + } + + @Override + public void visitReference(JCMemberReference tree) { + if (types.isFunctionalInterface(t.tsym) && + types.isFunctionalInterface(s.tsym) && + types.asSuper(t, s.tsym) == null && + types.asSuper(s, t.tsym) == null) { + Type desc_t = types.findDescriptorType(t); + Type desc_s = types.findDescriptorType(s); + if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) { + if (!desc_s.getReturnType().hasTag(VOID)) { + //perform structural comparison + Type ret_t = desc_t.getReturnType(); + Type ret_s = desc_s.getReturnType(); + result &= ((tree.refPolyKind == PolyKind.STANDALONE) + ? standaloneMostSpecific(ret_t, ret_s, tree.type, warn) + : polyMostSpecific(ret_t, ret_s, warn)); + } else { + return; + } + } else { + result &= false; + } + } else { + result &= MostSpecificCheckContext.super.compatible(t, s, warn); + } + } + + @Override + public void visitLambda(JCLambda tree) { + if (types.isFunctionalInterface(t.tsym) && + types.isFunctionalInterface(s.tsym) && + types.asSuper(t, s.tsym) == null && + types.asSuper(s, t.tsym) == null) { + Type desc_t = types.findDescriptorType(t); + Type desc_s = types.findDescriptorType(s); + if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT + || types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) { + if (!desc_s.getReturnType().hasTag(VOID)) { + //perform structural comparison + Type ret_t = desc_t.getReturnType(); + Type ret_s = desc_s.getReturnType(); + scanLambdaBody(tree, ret_t, ret_s); + } else { + return; + } + } else { + result &= false; + } + } else { + result &= MostSpecificCheckContext.super.compatible(t, s, warn); + } + } + //where + + void scanLambdaBody(JCLambda lambda, final Type t, final Type s) { + if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { + result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn); + } else { + DeferredAttr.LambdaReturnScanner lambdaScanner = + new DeferredAttr.LambdaReturnScanner() { + @Override + public void visitReturn(JCReturn tree) { + if (tree.expr != null) { + result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn); + } + } + }; + lambdaScanner.scan(lambda.body); + } + } + } + } + } + public static class InapplicableMethodException extends RuntimeException { private static final long serialVersionUID = 0; @@ -1142,153 +1351,32 @@ public class Resolve { } //where private boolean signatureMoreSpecific(List actuals, Env env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) { - Symbol m12 = adjustVarargs(m1, m2, useVarargs); - Symbol m22 = adjustVarargs(m2, m1, useVarargs); - Type mtype1 = types.memberType(site, m12); - Type mtype2 = types.memberType(site, m22); - - //check if invocation is more specific - if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) { - return true; - } - - //perform structural check - - List formals1 = mtype1.getParameterTypes(); - Type lastFormal1 = formals1.last(); - List formals2 = mtype2.getParameterTypes(); - Type lastFormal2 = formals2.last(); - ListBuffer newFormals = ListBuffer.lb(); - - boolean hasStructuralPoly = false; - for (Type actual : actuals) { - //perform formal argument adaptation in case actuals > formals (varargs) - Type f1 = formals1.isEmpty() ? - lastFormal1 : formals1.head; - Type f2 = formals2.isEmpty() ? - lastFormal2 : formals2.head; - - //is this a structural actual argument? - boolean isStructuralPoly = actual.hasTag(DEFERRED) && - (((DeferredType)actual).tree.hasTag(LAMBDA) || - ((DeferredType)actual).tree.hasTag(REFERENCE)); - - Type newFormal = f1; - - if (isStructuralPoly) { - //for structural arguments only - check that corresponding formals - //are related - if so replace formal with - hasStructuralPoly = true; - DeferredType dt = (DeferredType)actual; - Type t1 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m1, currentResolutionContext.step).apply(dt); - Type t2 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m2, currentResolutionContext.step).apply(dt); - if (t1.isErroneous() || t2.isErroneous() || !isStructuralSubtype(t1, t2)) { - //not structural subtypes - simply fail - return false; - } else { - newFormal = syms.botType; - } - } - - newFormals.append(newFormal); - if (newFormals.length() > mtype2.getParameterTypes().length()) { - //expand m2's type so as to fit the new formal arity (varargs) - m22.type = types.createMethodTypeWithParameters(m22.type, m22.type.getParameterTypes().append(f2)); - } - - formals1 = formals1.isEmpty() ? formals1 : formals1.tail; - formals2 = formals2.isEmpty() ? formals2 : formals2.tail; - } - - if (!hasStructuralPoly) { - //if no structural actual was found, we're done - return false; - } - //perform additional adaptation if actuals < formals (varargs) - for (Type t : formals1) { - newFormals.append(t); - } - //check if invocation (with tweaked args) is more specific - return invocationMoreSpecific(env, site, m22, newFormals.toList(), allowBoxing, useVarargs); + noteWarner.clear(); + int maxLength = Math.max( + Math.max(m1.type.getParameterTypes().length(), actuals.length()), + m2.type.getParameterTypes().length()); + Type mst = instantiate(env, site, m2, null, + adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null, + allowBoxing, useVarargs, new MostSpecificCheck(!allowBoxing, actuals), noteWarner); + return mst != null && + !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); } - //where - private boolean invocationMoreSpecific(Env env, Type site, Symbol m2, List argtypes1, boolean allowBoxing, boolean useVarargs) { - MethodResolutionContext prevContext = currentResolutionContext; - try { - currentResolutionContext = new MethodResolutionContext(); - currentResolutionContext.step = allowBoxing ? BOX : BASIC; - noteWarner.clear(); - Type mst = instantiate(env, site, m2, null, - types.lowerBounds(argtypes1), null, - allowBoxing, false, resolveMethodCheck, noteWarner); - return mst != null && - !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); - } finally { - currentResolutionContext = prevContext; - } - } - //where - private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) { - List fromArgs = from.type.getParameterTypes(); - List toArgs = to.type.getParameterTypes(); - if (useVarargs && - (from.flags() & VARARGS) != 0 && - (to.flags() & VARARGS) != 0) { - Type varargsTypeFrom = fromArgs.last(); - Type varargsTypeTo = toArgs.last(); - ListBuffer args = ListBuffer.lb(); - if (toArgs.length() < fromArgs.length()) { - //if we are checking a varargs method 'from' against another varargs - //method 'to' (where arity of 'to' < arity of 'from') then expand signature - //of 'to' to 'fit' arity of 'from' (this means adding fake formals to 'to' - //until 'to' signature has the same arity as 'from') - while (fromArgs.head != varargsTypeFrom) { - args.append(toArgs.head == varargsTypeTo ? types.elemtype(varargsTypeTo) : toArgs.head); - fromArgs = fromArgs.tail; - toArgs = toArgs.head == varargsTypeTo ? - toArgs : - toArgs.tail; - } - } else { - //formal argument list is same as original list where last - //argument (array type) is removed - args.appendList(toArgs.reverse().tail.reverse()); + private List adjustArgs(List args, Symbol msym, int length, boolean allowVarargs) { + if ((msym.flags() & VARARGS) != 0 && allowVarargs) { + Type varargsElem = types.elemtype(args.last()); + if (varargsElem == null) { + Assert.error("Bad varargs = " + args.last() + " " + msym); } - //append varargs element type as last synthetic formal - args.append(types.elemtype(varargsTypeTo)); - Type mtype = types.createMethodTypeWithParameters(to.type, args.toList()); - return new MethodSymbol(to.flags_field & ~VARARGS, to.name, mtype, to.owner); + List newArgs = args.reverse().tail.prepend(varargsElem).reverse(); + while (newArgs.length() < length) { + newArgs = newArgs.append(newArgs.last()); + } + return newArgs; } else { - return to; + return args; } } //where - boolean isStructuralSubtype(Type s, Type t) { - - Type ret_s = types.findDescriptorType(s).getReturnType(); - Type ret_t = types.findDescriptorType(t).getReturnType(); - - //covariant most specific check for function descriptor return type - if (!types.isSubtype(ret_s, ret_t)) { - return false; - } - - List args_s = types.findDescriptorType(s).getParameterTypes(); - List args_t = types.findDescriptorType(t).getParameterTypes(); - - //arity must be identical - if (args_s.length() != args_t.length()) { - return false; - } - - //invariant most specific check for function descriptor parameter types - if (!types.isSameTypes(args_t, args_s)) { - return false; - } - - return true; - } - //where Type mostSpecificReturnType(Type mt1, Type mt2) { Type rt1 = mt1.getReturnType(); Type rt2 = mt2.getReturnType(); @@ -2386,10 +2474,23 @@ public class Resolve { List typeargtypes, boolean boxingAllowed) { MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; + + ReferenceLookupHelper boundLookupHelper; + if (!name.equals(names.init)) { + //method reference + boundLookupHelper = + new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); + } else if (site.hasTag(ARRAY)) { + //array constructor reference + boundLookupHelper = + new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); + } else { + //class constructor reference + boundLookupHelper = + new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); + } + //step 1 - bound lookup - ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ? - new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase) : - new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); Env boundEnv = env.dup(env.tree, env.info.dup()); Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper); @@ -2626,6 +2727,33 @@ public class Resolve { } } + /** + * Helper class for array constructor lookup; an array constructor lookup + * is simulated by looking up a method that returns the array type specified + * as qualifier, and that accepts a single int parameter (size of the array). + */ + class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper { + + ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List argtypes, + List typeargtypes, MethodResolutionPhase maxPhase) { + super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); + } + + @Override + protected Symbol lookup(Env env, MethodResolutionPhase phase) { + Scope sc = new Scope(syms.arrayClass); + MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym); + arrayConstr.type = new MethodType(List.of(syms.intType), site, List.nil(), syms.methodClass); + sc.enter(arrayConstr); + return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false, false); + } + + @Override + ReferenceKind referenceKind(Symbol sym) { + return ReferenceKind.ARRAY_CTOR; + } + } + /** * Helper class for constructor reference lookup. The lookup logic is based * upon either Resolve.findMethod or Resolve.findDiamond - depending on @@ -3381,7 +3509,10 @@ public class Resolve { @Override protected Symbol access(Name name, TypeSymbol location) { - return ambiguousSyms.last(); + Symbol firstAmbiguity = ambiguousSyms.last(); + return firstAmbiguity.kind == TYP ? + types.createErrorType(name, location, firstAmbiguity.type).tsym : + firstAmbiguity; } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index 76ca8f68ea2..0b191293db7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -483,6 +483,7 @@ public class TransTypes extends TreeTranslator { tree.restype = translate(tree.restype, null); tree.typarams = List.nil(); tree.params = translateVarDefs(tree.params); + tree.recvparam = translate(tree.recvparam, null); tree.thrown = translate(tree.thrown, null); tree.body = translate(tree.body, tree.sym.erasure(types).getReturnType()); tree.type = erasure(tree.type); @@ -549,9 +550,6 @@ public class TransTypes extends TreeTranslator { currentMethod = null; tree.params = translate(tree.params); tree.body = translate(tree.body, null); - //save non-erased target - tree.targetType = tree.type; - Assert.check(!tree.targetType.isCompound(), "Intersection-type targets not supported yet!"); tree.type = erasure(tree.type); result = tree; } @@ -785,9 +783,6 @@ public class TransTypes extends TreeTranslator { public void visitReference(JCMemberReference tree) { tree.expr = translate(tree.expr, null); - //save non-erased target - tree.targetType = tree.type; - Assert.check(!tree.targetType.isCompound(), "Intersection-type targets not supported yet!"); tree.type = erasure(tree.type); result = tree; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 33ee5a780fb..4061471be55 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -351,8 +351,8 @@ public class ClassReader implements Completer { /** Read a byte. */ - byte nextByte() { - return buf[bp++]; + int nextByte() { + return buf[bp++] & 0xFF; } /** Read an integer. @@ -1172,6 +1172,19 @@ public class ClassReader implements Completer { } }, + new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { + protected void read(Symbol sym, int attrLen) { + attachTypeAnnotations(sym); + } + }, + + new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) { + protected void read(Symbol sym, int attrLen) { + attachTypeAnnotations(sym); + } + }, + + // The following attributes for a Code attribute are not currently handled // StackMapTable // SourceDebugExtension @@ -1381,6 +1394,17 @@ public class ClassReader implements Completer { } } + void attachTypeAnnotations(final Symbol sym) { + int numAttributes = nextChar(); + if (numAttributes != 0) { + ListBuffer proxies = + ListBuffer.lb(); + for (int i = 0; i < numAttributes; i++) + proxies.append(readTypeAnnotation()); + annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList())); + } + } + /** Attach the default value for an annotation element. */ void attachAnnotationDefault(final Symbol sym) { @@ -1427,6 +1451,111 @@ public class ClassReader implements Completer { return new CompoundAnnotationProxy(t, pairs.toList()); } + TypeAnnotationProxy readTypeAnnotation() { + TypeAnnotationPosition position = readPosition(); + CompoundAnnotationProxy proxy = readCompoundAnnotation(); + + return new TypeAnnotationProxy(proxy, position); + } + + TypeAnnotationPosition readPosition() { + int tag = nextByte(); // TargetType tag is a byte + + if (!TargetType.isValidTargetTypeValue(tag)) + throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag)); + + TypeAnnotationPosition position = new TypeAnnotationPosition(); + TargetType type = TargetType.fromTargetTypeValue(tag); + + position.type = type; + + switch (type) { + // type cast + case CAST: + // instanceof + case INSTANCEOF: + // new expression + case NEW: + position.offset = nextChar(); + break; + // local variable + case LOCAL_VARIABLE: + // resource variable + case RESOURCE_VARIABLE: + int table_length = nextChar(); + position.lvarOffset = new int[table_length]; + position.lvarLength = new int[table_length]; + position.lvarIndex = new int[table_length]; + + for (int i = 0; i < table_length; ++i) { + position.lvarOffset[i] = nextChar(); + position.lvarLength[i] = nextChar(); + position.lvarIndex[i] = nextChar(); + } + break; + // exception parameter + case EXCEPTION_PARAMETER: + position.exception_index = nextByte(); + break; + // method receiver + case METHOD_RECEIVER: + // Do nothing + break; + // type parameter + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: + position.parameter_index = nextByte(); + break; + // type parameter bound + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + position.parameter_index = nextByte(); + position.bound_index = nextByte(); + break; + // class extends or implements clause + case CLASS_EXTENDS: + position.type_index = nextChar(); + break; + // throws + case THROWS: + position.type_index = nextChar(); + break; + // method parameter + case METHOD_FORMAL_PARAMETER: + position.parameter_index = nextByte(); + break; + // method/constructor/reference type argument + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: + position.offset = nextChar(); + position.type_index = nextByte(); + break; + // We don't need to worry about these + case METHOD_RETURN: + case FIELD: + break; + // lambda formal parameter + case LAMBDA_FORMAL_PARAMETER: + position.parameter_index = nextByte(); + break; + case UNKNOWN: + throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!"); + default: + throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + position); + } + + { // See whether there is location info and read it + int len = nextByte(); + ListBuffer loc = ListBuffer.lb(); + for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) + loc = loc.append(nextByte()); + position.location = TypeAnnotationPosition.getTypePathFromBinary(loc.toList()); + } + + return position; + } + Attribute readAttributeValue() { char c = (char) buf[bp++]; switch (c) { @@ -1748,7 +1877,7 @@ public class ClassReader implements Completer { Annotations annotations = sym.annotations; List newList = deproxyCompoundList(l); if (annotations.pendingCompletion()) { - annotations.setAttributes(newList); + annotations.setDeclarationAttributes(newList); } else { annotations.append(newList); } @@ -1758,6 +1887,39 @@ public class ClassReader implements Completer { } } + class TypeAnnotationCompleter extends AnnotationCompleter { + + List proxies; + + TypeAnnotationCompleter(Symbol sym, + List proxies) { + super(sym, List.nil()); + this.proxies = proxies; + } + + List deproxyTypeCompoundList(List proxies) { + ListBuffer buf = ListBuffer.lb(); + for (TypeAnnotationProxy proxy: proxies) { + Attribute.Compound compound = deproxyCompound(proxy.compound); + Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); + buf.add(typeCompound); + } + return buf.toList(); + } + + @Override + public void enterAnnotation() { + JavaFileObject previousClassFile = currentClassFile; + try { + currentClassFile = classFile; + List newList = deproxyTypeCompoundList(proxies); + sym.annotations.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes())); + } finally { + currentClassFile = previousClassFile; + } + } + } + /************************************************************************ * Reading Symbols diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 329000d3e4f..8c1e3204c5d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -31,12 +31,14 @@ import java.util.Map; import java.util.Set; import java.util.HashSet; +import javax.lang.model.type.TypeKind; import javax.tools.JavaFileManager; import javax.tools.FileObject; import javax.tools.JavaFileObject; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.RetentionPolicy; +import com.sun.tools.javac.code.Attribute.TypeCompound; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Types.UniqueType; @@ -47,7 +49,6 @@ import com.sun.tools.javac.jvm.Pool.MethodHandle; import com.sun.tools.javac.jvm.Pool.Variable; import com.sun.tools.javac.util.*; -import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.*; @@ -68,19 +69,17 @@ public class ClassWriter extends ClassFile { protected static final Context.Key classWriterKey = new Context.Key(); - private final Symtab syms; - private final Options options; /** Switch: verbose output. */ private boolean verbose; - /** Switch: scramble private names. + /** Switch: scramble private field names. */ private boolean scramble; - /** Switch: scramble private names. + /** Switch: scramble all field names. */ private boolean scrambleAll; @@ -96,7 +95,7 @@ public class ClassWriter extends ClassFile { */ private boolean genCrt; - /** Switch: describe the generated stackmap + /** Switch: describe the generated stackmap. */ boolean debugstackmap; @@ -114,7 +113,7 @@ public class ClassWriter extends ClassFile { private Types types; /** The initial sizes of the data and constant pool buffers. - * sizes are increased when buffers get full. + * Sizes are increased when buffers get full. */ static final int DATA_BUF_SIZE = 0x0fff0; static final int POOL_BUF_SIZE = 0x1fff0; @@ -181,7 +180,6 @@ public class ClassWriter extends ClassFile { log = Log.instance(context); names = Names.instance(context); - syms = Symtab.instance(context); options = Options.instance(context); target = Target.instance(context); source = Source.instance(context); @@ -279,6 +277,7 @@ public class ClassWriter extends ClassFile { /** Assemble signature of given type in string buffer. */ void assembleSig(Type type) { + type = type.unannotatedType(); switch (type.getTag()) { case BYTE: sigbuf.appendByte('B'); @@ -379,6 +378,7 @@ public class ClassWriter extends ClassFile { } void assembleClassSig(Type type) { + type = type.unannotatedType(); ClassType ct = (ClassType)type; ClassSymbol c = (ClassSymbol)ct.tsym; enterInner(c); @@ -482,10 +482,8 @@ public class ClassWriter extends ClassFile { while (i < pool.pp) { Object value = pool.pool[i]; Assert.checkNonNull(value); - if (value instanceof Method) - value = ((Method)value).m; - else if (value instanceof Variable) - value = ((Variable)value).v; + if (value instanceof Method || value instanceof Variable) + value = ((DelegatedSymbol)value).getUnderlyingSymbol(); if (value instanceof MethodSymbol) { MethodSymbol m = (MethodSymbol)value; @@ -722,6 +720,7 @@ public class ClassWriter extends ClassFile { acount++; } acount += writeJavaAnnotations(sym.getRawAttributes()); + acount += writeTypeAnnotations(sym.getRawTypeAttributes()); return acount; } @@ -838,6 +837,76 @@ public class ClassWriter extends ClassFile { return attrCount; } + int writeTypeAnnotations(List typeAnnos) { + if (typeAnnos.isEmpty()) return 0; + + ListBuffer visibles = ListBuffer.lb(); + ListBuffer invisibles = ListBuffer.lb(); + + for (Attribute.TypeCompound tc : typeAnnos) { + if (tc.position == null || tc.position.type == TargetType.UNKNOWN) { + boolean found = false; + // TODO: the position for the container annotation of a + // repeating type annotation has to be set. + // This cannot be done when the container is created, because + // then the position is not determined yet. + // How can we link these pieces better together? + if (tc.values.size() == 1) { + Pair val = tc.values.get(0); + if (val.fst.getSimpleName().contentEquals("value") && + val.snd instanceof Attribute.Array) { + Attribute.Array arr = (Attribute.Array) val.snd; + if (arr.values.length != 0 && + arr.values[0] instanceof Attribute.TypeCompound) { + TypeCompound atycomp = (Attribute.TypeCompound) arr.values[0]; + if (atycomp.position.type != TargetType.UNKNOWN) { + tc.position = atycomp.position; + found = true; + } + } + } + } + if (!found) { + // This happens for nested types like @A Outer. @B Inner. + // For method parameters we get the annotation twice! Once with + // a valid position, once unknown. + // TODO: find a cleaner solution. + // System.err.println("ClassWriter: Position UNKNOWN in type annotation: " + tc); + continue; + } + } + if (!tc.position.emitToClassfile()) + continue; + switch (types.getRetention(tc)) { + case SOURCE: break; + case CLASS: invisibles.append(tc); break; + case RUNTIME: visibles.append(tc); break; + default: ;// /* fail soft */ throw new AssertionError(vis); + } + } + + int attrCount = 0; + if (visibles.length() != 0) { + int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations); + databuf.appendChar(visibles.length()); + for (Attribute.TypeCompound p : visibles) + writeTypeAnnotation(p); + endAttr(attrIndex); + attrCount++; + } + + if (invisibles.length() != 0) { + int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations); + databuf.appendChar(invisibles.length()); + for (Attribute.TypeCompound p : invisibles) + writeTypeAnnotation(p); + endAttr(attrIndex); + attrCount++; + } + + return attrCount; + } + /** A visitor to write an attribute including its leading * single-character marker. */ @@ -914,6 +983,94 @@ public class ClassWriter extends ClassFile { p.snd.accept(awriter); } } + + void writeTypeAnnotation(Attribute.TypeCompound c) { + writePosition(c.position); + writeCompoundAttribute(c); + } + + void writePosition(TypeAnnotationPosition p) { + databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte + switch (p.type) { + // type cast + case CAST: + // instanceof + case INSTANCEOF: + // new expression + case NEW: + databuf.appendChar(p.offset); + break; + // local variable + case LOCAL_VARIABLE: + // resource variable + case RESOURCE_VARIABLE: + databuf.appendChar(p.lvarOffset.length); // for table length + for (int i = 0; i < p.lvarOffset.length; ++i) { + databuf.appendChar(p.lvarOffset[i]); + databuf.appendChar(p.lvarLength[i]); + databuf.appendChar(p.lvarIndex[i]); + } + break; + // exception parameter + case EXCEPTION_PARAMETER: + databuf.appendByte(p.exception_index); + break; + // method receiver + case METHOD_RECEIVER: + // Do nothing + break; + // type parameter + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: + databuf.appendByte(p.parameter_index); + break; + // type parameter bound + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + databuf.appendByte(p.parameter_index); + databuf.appendByte(p.bound_index); + break; + // class extends or implements clause + case CLASS_EXTENDS: + databuf.appendChar(p.type_index); + break; + // throws + case THROWS: + databuf.appendChar(p.type_index); + break; + // method parameter + case METHOD_FORMAL_PARAMETER: + databuf.appendByte(p.parameter_index); + break; + // method/constructor/reference type argument + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: + databuf.appendChar(p.offset); + databuf.appendByte(p.type_index); + break; + // We don't need to worry about these + case METHOD_RETURN: + case FIELD: + break; + // lambda formal parameter + case LAMBDA_FORMAL_PARAMETER: + databuf.appendByte(p.parameter_index); + break; + case UNKNOWN: + throw new AssertionError("jvm.ClassWriter: UNKNOWN target type should never occur!"); + default: + throw new AssertionError("jvm.ClassWriter: Unknown target type for position: " + p); + } + + { // Append location data for generics/arrays. + databuf.appendByte(p.location.size()); + java.util.List loc = TypeAnnotationPosition.getBinaryFromTypePath(p.location); + for (int i : loc) + databuf.appendByte((byte)i); + } + } + /********************************************************************** * Writing Objects **********************************************************************/ @@ -1661,6 +1818,7 @@ public class ClassWriter extends ClassFile { acount += writeFlagAttrs(c.flags()); acount += writeJavaAnnotations(c.getRawAttributes()); + acount += writeTypeAnnotations(c.getRawTypeAttributes()); acount += writeEnclosingMethodAttribute(c); acount += writeExtraClassAttributes(c); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java index 87e1d6aea76..f5f37ef0435 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1924,17 +1924,70 @@ public class Code { if (length < Character.MAX_VALUE) { v.length = length; putVar(v); + fillLocalVarPosition(v); } } } state.defined.excl(adr); } + private void fillLocalVarPosition(LocalVar lv) { + if (lv == null || lv.sym == null + || lv.sym.annotations.isTypesEmpty()) + return; + for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { + TypeAnnotationPosition p = ta.position; + p.lvarOffset = new int[] { (int)lv.start_pc }; + p.lvarLength = new int[] { (int)lv.length }; + p.lvarIndex = new int[] { (int)lv.reg }; + p.isValidOffset = true; + } + } + + // Method to be called after compressCatchTable to + // fill in the exception table index for type + // annotations on exception parameters. + public void fillExceptionParameterPositions() { + for (int i = 0; i < varBufferSize; ++i) { + LocalVar lv = varBuffer[i]; + if (lv == null || lv.sym == null + || lv.sym.annotations.isTypesEmpty() + || !lv.sym.isExceptionParameter()) + return; + + int exidx = findExceptionIndex(lv); + + for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { + TypeAnnotationPosition p = ta.position; + p.exception_index = exidx; + } + } + } + + private int findExceptionIndex(LocalVar lv) { + List iter = catchInfo.toList(); + int len = catchInfo.length(); + for (int i = 0; i < len; ++i) { + char[] catchEntry = iter.head; + iter = iter.tail; + char handlerpc = catchEntry[2]; + if (lv.start_pc == handlerpc + 1) { + return i; + } + } + return -1; + } + /** Put a live variable range into the buffer to be output to the * class file. */ void putVar(LocalVar var) { - if (!varDebugInfo) return; + // Keep local variables if + // 1) we need them for debug information + // 2) it is an exception type and it contains type annotations + if (!varDebugInfo && + (!var.sym.isExceptionParameter() || + var.sym.annotations.isTypesEmpty())) return; if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return; if (varBuffer == null) varBuffer = new LocalVar[20]; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java index f99c48b258c..b450fdcf43e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1016,8 +1016,11 @@ public class Gen extends JCTree.Visitor { code.frameBeforeLast = null; } - //compress exception table + // Compress exception table code.compressCatchTable(); + + // Fill in type annotation positions for exception parameters + code.fillExceptionParameterPositions(); } } @@ -1738,6 +1741,7 @@ public class Gen extends JCTree.Visitor { *************************************************************************/ public void visitApply(JCMethodInvocation tree) { + setTypeAnnotationPositions(tree.pos); // Generate code for method. Item m = genExpr(tree.meth, methodType); // Generate code for all arguments, where the expected types are @@ -1775,10 +1779,48 @@ public class Gen extends JCTree.Visitor { result = items.makeStackItem(pt); } + private void setTypeAnnotationPositions(int treePos) { + MethodSymbol meth = code.meth; + + for (Attribute.TypeCompound ta : meth.getRawTypeAttributes()) { + if (ta.position.pos == treePos) { + ta.position.offset = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; + ta.position.isValidOffset = true; + } + } + + if (code.meth.getKind() != javax.lang.model.element.ElementKind.CONSTRUCTOR + && code.meth.getKind() != javax.lang.model.element.ElementKind.STATIC_INIT) + return; + + for (Attribute.TypeCompound ta : meth.owner.getRawTypeAttributes()) { + if (ta.position.pos == treePos) { + ta.position.offset = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; + ta.position.isValidOffset = true; + } + } + + ClassSymbol clazz = meth.enclClass(); + for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) { + if (!s.getKind().isField()) + continue; + for (Attribute.TypeCompound ta : s.getRawTypeAttributes()) { + if (ta.position.pos == treePos) { + ta.position.offset = code.cp; + ta.position.lvarOffset = new int[] { code.cp }; + ta.position.isValidOffset = true; + } + } + } + } + public void visitNewClass(JCNewClass tree) { // Enclosing instances or anonymous classes should have been eliminated // by now. Assert.check(tree.encl == null && tree.def == null); + setTypeAnnotationPositions(tree.pos); code.emitop2(new_, makeRef(tree.pos(), tree.type)); code.emitop0(dup); @@ -1793,6 +1835,7 @@ public class Gen extends JCTree.Visitor { } public void visitNewArray(JCNewArray tree) { + setTypeAnnotationPositions(tree.pos); if (tree.elems != null) { Type elemtype = types.elemtype(tree.type); @@ -2122,6 +2165,7 @@ public class Gen extends JCTree.Visitor { } public void visitTypeCast(JCTypeCast tree) { + setTypeAnnotationPositions(tree.pos); result = genExpr(tree.expr, tree.clazz.type).load(); // Additional code is only needed if we cast to a reference type // which is not statically a supertype of the expression's type. @@ -2138,6 +2182,7 @@ public class Gen extends JCTree.Visitor { } public void visitTypeTest(JCInstanceOf tree) { + setTypeAnnotationPositions(tree.pos); genExpr(tree.expr, tree.expr.type).load(); code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type)); result = items.makeStackItem(syms.booleanType); @@ -2184,7 +2229,7 @@ public class Gen extends JCTree.Visitor { code.emitop2(ldc2, makeRef(tree.pos(), tree.selected.type)); result = items.makeStackItem(pt); return; - } + } Symbol ssym = TreeInfo.symbol(tree.selected); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java index b1b8444bd6f..139ba519a9f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -158,7 +158,7 @@ public class JNIWriter { return false; /* temporary code for backwards compatibility */ - for (Attribute.Compound a: c.annotations.getAttributes()) { + for (Attribute.Compound a: c.annotations.getDeclarationAttributes()) { if (a.type.tsym == syms.nativeHeaderType_old.tsym) return true; } @@ -167,7 +167,7 @@ public class JNIWriter { for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) { if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0) return true; - for (Attribute.Compound a: i.sym.annotations.getAttributes()) { + for (Attribute.Compound a: i.sym.annotations.getDeclarationAttributes()) { if (a.type.tsym == syms.nativeHeaderType.tsym) return true; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java index 08a5d57d87f..553cc3ae1a1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -140,23 +140,23 @@ public class Pool { return n == null ? -1 : n.intValue(); } - static class Method extends DelegatedSymbol { - MethodSymbol m; + static class Method extends DelegatedSymbol { UniqueType uniqueType; Method(MethodSymbol m, Types types) { super(m); - this.m = m; this.uniqueType = new UniqueType(m.type, types); } - public boolean equals(Object other) { - if (!(other instanceof Method)) return false; - MethodSymbol o = ((Method)other).m; + public boolean equals(Object any) { + if (!(any instanceof Method)) return false; + MethodSymbol o = ((Method)any).other; + MethodSymbol m = this.other; return o.name == m.name && o.owner == m.owner && - ((Method)other).uniqueType.equals(uniqueType); + ((Method)any).uniqueType.equals(uniqueType); } public int hashCode() { + MethodSymbol m = this.other; return m.name.hashCode() * 33 + m.owner.hashCode() * 9 + @@ -173,21 +173,21 @@ public class Pool { } @Override - public boolean equals(Object other) { - if (!super.equals(other)) return false; - if (!(other instanceof DynamicMethod)) return false; - DynamicMethodSymbol dm1 = (DynamicMethodSymbol)m; - DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)other).m; + public boolean equals(Object any) { + if (!super.equals(any)) return false; + if (!(any instanceof DynamicMethod)) return false; + DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other; + DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other; return dm1.bsm == dm2.bsm && dm1.bsmKind == dm2.bsmKind && Arrays.equals(uniqueStaticArgs, - ((DynamicMethod)other).uniqueStaticArgs); + ((DynamicMethod)any).uniqueStaticArgs); } @Override public int hashCode() { int hash = super.hashCode(); - DynamicMethodSymbol dm = (DynamicMethodSymbol)m; + DynamicMethodSymbol dm = (DynamicMethodSymbol)other; hash += dm.bsmKind * 7 + dm.bsm.hashCode() * 11; for (int i = 0; i < dm.staticArgs.length; i++) { @@ -209,23 +209,23 @@ public class Pool { } } - static class Variable extends DelegatedSymbol { - VarSymbol v; + static class Variable extends DelegatedSymbol { UniqueType uniqueType; Variable(VarSymbol v, Types types) { super(v); - this.v = v; this.uniqueType = new UniqueType(v.type, types); } - public boolean equals(Object other) { - if (!(other instanceof Variable)) return false; - VarSymbol o = ((Variable)other).v; + public boolean equals(Object any) { + if (!(any instanceof Variable)) return false; + VarSymbol o = ((Variable)any).other; + VarSymbol v = other; return o.name == v.name && o.owner == v.owner && - ((Variable)other).uniqueType.equals(uniqueType); + ((Variable)any).uniqueType.equals(uniqueType); } public int hashCode() { + VarSymbol v = other; return v.name.hashCode() * 33 + v.owner.hashCode() * 9 + diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 40fbd22bd25..fc4786a2a60 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -513,7 +513,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { */ public CompileState shouldStopPolicyIfNoError; - /** A queue of all as yet unattributed classes.oLo + /** A queue of all as yet unattributed classes. */ public Todo todo; @@ -629,6 +629,8 @@ public class JavaCompiler implements ClassReader.SourceCompleter { if (!taskListener.isEmpty()) { TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); taskListener.started(e); + keepComments = true; + genEndPos = true; } Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); tree = parser.parseCompilationUnit(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java index 168cef93e72..5861e70f7f3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -27,6 +27,8 @@ package com.sun.tools.javac.model; import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Map; import javax.lang.model.SourceVersion; @@ -96,32 +98,43 @@ public class JavacElements implements Elements { enter = Enter.instance(context); } - /** - * An internal-use utility that creates a reified annotation. + * An internal-use utility that creates a runtime view of an + * annotation. This is the implementation of + * Element.getAnnotation(Class). */ public static A getAnnotation(Symbol annotated, Class annoType) { if (!annoType.isAnnotation()) throw new IllegalArgumentException("Not an annotation type: " + annoType); - String name = annoType.getName(); - for (Attribute.Compound anno : annotated.getAnnotationMirrors()) - if (name.equals(anno.type.tsym.flatName().toString())) - return AnnotationProxyMaker.generateAnnotation(anno, annoType); - return null; + Attribute.Compound c; + if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) { + c = getAttributeOnClass((ClassSymbol)annotated, annoType); + } else { + c = getAttribute(annotated, annoType); + } + return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType); } - /** - * An internal-use utility that creates a reified annotation. - * This overloaded version take annotation inheritance into account. - */ - public static A getAnnotation(ClassSymbol annotated, - Class annoType) { + // Helper to getAnnotation[s] + private static Attribute.Compound getAttribute(Symbol annotated, + Class annoType) { + String name = annoType.getName(); + + for (Attribute.Compound anno : annotated.getRawAttributes()) + if (name.equals(anno.type.tsym.flatName().toString())) + return anno; + + return null; + } + // Helper to getAnnotation[s] + private static Attribute.Compound getAttributeOnClass(ClassSymbol annotated, + Class annoType) { boolean inherited = annoType.isAnnotationPresent(Inherited.class); - A result = null; + Attribute.Compound result = null; while (annotated.name != annotated.name.table.names.java_lang_Object) { - result = getAnnotation((Symbol)annotated, annoType); + result = getAttribute(annotated, annoType); if (result != null || !inherited) break; Type sup = annotated.getSuperclass(); @@ -132,6 +145,189 @@ public class JavacElements implements Elements { return result; } + /** + * An internal-use utility that creates a runtime view of + * annotations. This is the implementation of + * Element.getAnnotations(Class). + */ + public static A[] getAnnotations(Symbol annotated, + Class annoType) { + if (!annoType.isAnnotation()) + throw new IllegalArgumentException("Not an annotation type: " + + annoType); + // If annoType does not declare a container this is equivalent to wrapping + // getAnnotation(...) in an array. + Class containerType = getContainer(annoType); + if (containerType == null) { + A res = getAnnotation(annotated, annoType); + int size; + if (res == null) { + size = 0; + } else { + size = 1; + } + @SuppressWarnings("unchecked") // annoType is the Class for A + A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); + if (res != null) + arr[0] = res; + return arr; + } + + // So we have a containing type + String name = annoType.getName(); + String annoTypeName = annoType.getSimpleName(); + String containerTypeName = containerType.getSimpleName(); + int directIndex = -1, containerIndex = -1; + Attribute.Compound direct = null, container = null; + Attribute.Compound[] rawAttributes = annotated.getRawAttributes().toArray(new Attribute.Compound[0]); + + // Find directly present annotations + for (int i = 0; i < rawAttributes.length; i++) { + if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { + directIndex = i; + direct = rawAttributes[i]; + } else if(containerTypeName != null && + containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { + containerIndex = i; + container = rawAttributes[i]; + } + } + // Deal with inherited annotations + if (annotated.kind == Kinds.TYP && + (annotated instanceof ClassSymbol)) { + ClassSymbol s = (ClassSymbol)annotated; + if (direct == null && container == null) { + direct = getAttributeOnClass(s, annoType); + container = getAttributeOnClass(s, containerType); + + // both are inherited and found, put container last + if (direct != null && container != null) { + directIndex = 0; + containerIndex = 1; + } else if (direct != null) { + directIndex = 0; + } else { + containerIndex = 0; + } + } else if (direct == null) { + direct = getAttributeOnClass(s, annoType); + if (direct != null) + directIndex = containerIndex + 1; + } else if (container == null) { + container = getAttributeOnClass(s, containerType); + if (container != null) + containerIndex = directIndex + 1; + } + } + + // Pack them in an array + Attribute[] contained0 = new Attribute[0]; + if (container != null) + contained0 = unpackAttributes(container); + ListBuffer compounds = ListBuffer.lb(); + for (Attribute a : contained0) + if (a instanceof Attribute.Compound) + compounds = compounds.append((Attribute.Compound)a); + Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]); + + int size = (direct == null ? 0 : 1) + contained.length; + @SuppressWarnings("unchecked") // annoType is the Class for A + A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); + + // if direct && container, which is first? + int insert = -1; + int length = arr.length; + if (directIndex >= 0 && containerIndex >= 0) { + if (directIndex < containerIndex) { + arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + insert = 1; + } else { + arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + insert = 0; + length--; + } + } else if (directIndex >= 0) { + arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + return arr; + } else { + // Only container + insert = 0; + } + + for (int i = 0; i + insert < length; i++) + arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType); + + return arr; + } + + // Needed to unpack the runtime view of containing annotations + private static final Class REPEATABLE_CLASS = initRepeatable(); + private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod(); + + private static Class initRepeatable() { + try { + // Repeatable will not be available when bootstrapping on + // JDK 7 so use a reflective lookup instead of a class + // literal for Repeatable.class. + return Class.forName("java.lang.annotation.Repeatable").asSubclass(Annotation.class); + } catch (ClassNotFoundException e) { + return null; + } catch (SecurityException e) { + return null; + } + } + private static Method initValueElementMethod() { + if (REPEATABLE_CLASS == null) + return null; + + Method m = null; + try { + m = REPEATABLE_CLASS.getMethod("value"); + if (m != null) + m.setAccessible(true); + return m; + } catch (NoSuchMethodException e) { + return null; + } + } + + // Helper to getAnnotations + private static Class getContainer(Class annoType) { + // Since we can not refer to java.lang.annotation.Repeatable until we are + // bootstrapping with java 8 we need to get the Repeatable annotation using + // reflective invocations instead of just using its type and element method. + if (REPEATABLE_CLASS != null && + VALUE_ELEMENT_METHOD != null) { + // Get the Repeatable instance on the annotations declaration + Annotation repeatable = (Annotation)annoType.getAnnotation(REPEATABLE_CLASS); + if (repeatable != null) { + try { + // Get the value element, it should be a class + // indicating the containing annotation type + @SuppressWarnings("unchecked") + Class containerType = (Class)VALUE_ELEMENT_METHOD.invoke(repeatable); + if (containerType == null) + return null; + + return containerType; + } catch (ClassCastException e) { + return null; + } catch (IllegalAccessException e) { + return null; + } catch (InvocationTargetException e ) { + return null; + } + } + } + return null; + } + // Helper to getAnnotations + private static Attribute[] unpackAttributes(Attribute.Compound container) { + // We now have an instance of the container, + // unpack it returning an instance of the + // contained type or null + return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values; + } public PackageSymbol getPackageElement(CharSequence name) { String strName = name.toString(); @@ -238,8 +434,10 @@ public class JavacElements implements Elements { tree.accept(vis); if (vis.result == null) return null; + + List annos = sym.getRawAttributes(); return matchAnnoToTree(cast(Attribute.Compound.class, findme), - sym.getAnnotationMirrors(), + annos, vis.result); } @@ -442,7 +640,7 @@ public class JavacElements implements Elements { */ public List getAllAnnotationMirrors(Element e) { Symbol sym = cast(Symbol.class, e); - List annos = sym.getAnnotationMirrors(); + List annos = sym.getRawAttributes(); while (sym.getKind() == ElementKind.CLASS) { Type sup = ((ClassSymbol) sym).getSuperclass(); if (!sup.hasTag(CLASS) || sup.isErroneous() || @@ -451,7 +649,8 @@ public class JavacElements implements Elements { } sym = sup.tsym; List oldAnnos = annos; - for (Attribute.Compound anno : sym.getAnnotationMirrors()) { + List newAnnos = sym.getRawAttributes(); + for (Attribute.Compound anno : newAnnos) { if (isInherited(anno.type) && !containsAnnoOfType(oldAnnos, anno.type)) { annos = annos.prepend(anno); @@ -465,11 +664,7 @@ public class JavacElements implements Elements { * Tests whether an annotation type is @Inherited. */ private boolean isInherited(Type annotype) { - for (Attribute.Compound anno : annotype.tsym.getAnnotationMirrors()) { - if (anno.type.tsym == syms.inheritedType.tsym) - return true; - } - return false; + return annotype.tsym.attribute(syms.inheritedType.tsym) != null; } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java index 83ce128cd35..9d8933daa5c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -25,9 +25,9 @@ package com.sun.tools.javac.model; +import java.lang.annotation.Annotation; import java.util.Collections; import java.util.EnumSet; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -333,4 +333,28 @@ public class JavacTypes implements javax.lang.model.util.Types { return results; } + + public List typeAnnotationsOf(TypeMirror type) { + // TODO: these methods can be removed. + return null; // ((Type)type).typeAnnotations; + } + + public A typeAnnotationOf(TypeMirror type, + Class annotationType) { + // TODO: these methods can be removed. + return null; // JavacElements.getAnnotation(((Type)type).typeAnnotations, annotationType); + } + + public TypeMirror receiverTypeOf(ExecutableType type) { + return ((Type)type).asMethodType().recvtype; + } + + /* + public A receiverTypeAnnotationOf( + ExecutableType type, Class annotationType) { + return JavacElements.getAnnotation( + ((Type)type).asMethodType().receiverTypeAnnotations, + annotationType); + }*/ + } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java index 989e42d066e..bbc4d81d5c7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -279,13 +279,7 @@ public class DocCommentParser { try { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; - - Name name = names.fromChars(buf, namePos, nameLen); + Name name = readIdentifier(); TagParser tp = tagParsers.get(name); if (tp == null) { List content = blockContent(); @@ -334,14 +328,9 @@ public class DocCommentParser { try { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); - Name name = names.fromChars(buf, namePos, nameLen); TagParser tp = tagParsers.get(name); if (tp == null) { DCTree text = inlineText(); @@ -575,10 +564,8 @@ public class DocCommentParser { int pos = bp; if (isJavaIdentifierStart(ch)) { - nextChar(); - while (isJavaIdentifierPart(ch)) - nextChar(); - return m.at(pos).Identifier(names.fromChars(buf, pos, bp - pos)); + Name name = readJavaIdentifier(); + return m.at(pos).Identifier(name); } throw new ParseException("dc.identifier.expected"); @@ -703,39 +690,36 @@ public class DocCommentParser { protected DCTree entity() { int p = bp; nextChar(); - int namep = bp; + Name name = null; boolean checkSemi = false; if (ch == '#') { + int namep = bp; nextChar(); if (isDecimalDigit(ch)) { nextChar(); while (isDecimalDigit(ch)) nextChar(); - checkSemi = true; + name = names.fromChars(buf, namep, bp - namep); } else if (ch == 'x' || ch == 'X') { nextChar(); if (isHexDigit(ch)) { nextChar(); while (isHexDigit(ch)) nextChar(); - checkSemi = true; + name = names.fromChars(buf, namep, bp - namep); } } } else if (isIdentifierStart(ch)) { - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - checkSemi = true; + name = readIdentifier(); } - if (checkSemi && ch == ';') { + if (name == null) + return erroneous("dc.bad.entity", p); + else { + if (ch != ';') + return erroneous("dc.missing.semicolon", p); nextChar(); - return m.at(p).Entity(names.fromChars(buf, namep, bp - namep - 1)); - } else { - String code = checkSemi - ? "dc.missing.semicolon" - : "dc.bad.entity"; - return erroneous(code, p); + return m.at(p).Entity(name); } } @@ -747,11 +731,7 @@ public class DocCommentParser { int p = bp; nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); List attrs = htmlAttrs(); if (attrs != null) { boolean selfClosing = false; @@ -761,22 +741,16 @@ public class DocCommentParser { } if (ch == '>') { nextChar(); - Name name = names.fromChars(buf, namePos, nameLen); return m.at(p).StartElement(name, attrs, selfClosing); } } } else if (ch == '/') { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); if (ch == '>') { nextChar(); - Name name = names.fromChars(buf, namePos, nameLen); return m.at(p).EndElement(name); } } @@ -822,10 +796,7 @@ public class DocCommentParser { loop: while (isIdentifierStart(ch)) { int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); List value = null; ValueKind vkind = ValueKind.EMPTY; @@ -862,7 +833,6 @@ public class DocCommentParser { skipWhitespace(); value = v.toList(); } - Name name = names.fromChars(buf, namePos, nameLen); DCAttribute attr = m.at(namePos).Attribute(name, vkind, value); attrs.add(attr); } @@ -897,7 +867,7 @@ public class DocCommentParser { protected DCErroneous erroneous(String code, int pos) { int i = bp - 1; loop: - while (i > 0) { + while (i > pos) { switch (buf[i]) { case '\f': case '\n': case '\r': newline = true; @@ -926,16 +896,24 @@ public class DocCommentParser { return Character.isUnicodeIdentifierStart(ch); } - protected boolean isIdentifierPart(char ch) { - return Character.isUnicodeIdentifierPart(ch); + protected Name readIdentifier() { + int start = bp; + nextChar(); + while (bp < buflen && Character.isUnicodeIdentifierPart(ch)) + nextChar(); + return names.fromChars(buf, start, bp - start); } protected boolean isJavaIdentifierStart(char ch) { return Character.isJavaIdentifierStart(ch); } - protected boolean isJavaIdentifierPart(char ch) { - return Character.isJavaIdentifierPart(ch); + protected Name readJavaIdentifier() { + int start = bp; + nextChar(); + while (bp < buflen && Character.isJavaIdentifierPart(ch)) + nextChar(); + return names.fromChars(buf, start, bp - start); } protected boolean isDecimalDigit(char ch) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 28f6d8a29eb..52e8e087aa9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -88,6 +88,41 @@ public class JavacParser implements Parser { /** End position mappings container */ private final AbstractEndPosTable endPosTable; + // Because of javac's limited lookahead, some contexts are ambiguous in + // the presence of type annotations even though they are not ambiguous + // in the absence of type annotations. Consider this code: + // void m(String [] m) { } + // void m(String ... m) { } + // After parsing "String", javac calls bracketsOpt which immediately + // returns if the next character is not '['. Similarly, javac can see + // if the next token is ... and in that case parse an ellipsis. But in + // the presence of type annotations: + // void m(String @A [] m) { } + // void m(String @A ... m) { } + // no finite lookahead is enough to determine whether to read array + // levels or an ellipsis. Furthermore, if you call bracketsOpt, then + // bracketsOpt first reads all the leading annotations and only then + // discovers that it needs to fail. bracketsOpt needs a way to push + // back the extra annotations that it read. (But, bracketsOpt should + // not *always* be allowed to push back extra annotations that it finds + // -- in most contexts, any such extra annotation is an error. + // + // The following two variables permit type annotations that have + // already been read to be stored for later use. Alternate + // implementations are possible but would cause much larger changes to + // the parser. + + /** Type annotations that have already been read but have not yet been used. **/ + private List typeAnnotationsPushedBack = List.nil(); + + /** + * If the parser notices extra annotations, then it either immediately + * issues an error (if this variable is false) or places the extra + * annotations in variable typeAnnotationsPushedBack (if this variable + * is true). + */ + private boolean permitTypeAnnotationsPushBack = false; + interface ErrorRecoveryAction { JCTree doRecover(JavacParser parser); } @@ -124,9 +159,9 @@ public class JavacParser implements Parser { this.allowLambda = source.allowLambda(); this.allowMethodReferences = source.allowMethodReferences(); this.allowDefaultMethods = source.allowDefaultMethods(); - this.allowIntersectionTypesInCast = - source.allowIntersectionTypesInCast() && - fac.options.isSet("allowIntersectionTypes"); + this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); + this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast(); + this.allowTypeAnnotations = source.allowTypeAnnotations(); this.keepDocComments = keepDocComments; docComments = newDocCommentTable(keepDocComments, fac); this.keepLineMap = keepLineMap; @@ -200,6 +235,10 @@ public class JavacParser implements Parser { */ boolean allowDefaultMethods; + /** Switch: should we allow static methods in interfaces? + */ + boolean allowStaticInterfaceMethods; + /** Switch: should we allow intersection types in cast? */ boolean allowIntersectionTypesInCast; @@ -212,6 +251,20 @@ public class JavacParser implements Parser { */ boolean keepLineMap; + /** Switch: should we recognize type annotations? + */ + boolean allowTypeAnnotations; + + /** Switch: is "this" allowed as an identifier? + * This is needed to parse receiver types. + */ + boolean allowThisIdent; + + /** The type of the method receiver, as specified by a first "this" parameter. + */ + JCVariableDecl receiverParam; + + /** When terms are parsed, the mode determines which is expected: * mode = EXPR : an expression * mode = TYPE : a type @@ -245,40 +298,42 @@ public class JavacParser implements Parser { token = S.token(); } - protected boolean peekToken(TokenKind tk) { + protected boolean peekToken(Filter tk) { return peekToken(0, tk); } - protected boolean peekToken(int lookahead, TokenKind tk) { - return S.token(lookahead + 1).kind == tk; + protected boolean peekToken(int lookahead, Filter tk) { + return tk.accepts(S.token(lookahead + 1).kind); } - protected boolean peekToken(TokenKind tk1, TokenKind tk2) { + protected boolean peekToken(Filter tk1, Filter tk2) { return peekToken(0, tk1, tk2); } - protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2) { - return S.token(lookahead + 1).kind == tk1 && - S.token(lookahead + 2).kind == tk2; + protected boolean peekToken(int lookahead, Filter tk1, Filter tk2) { + return tk1.accepts(S.token(lookahead + 1).kind) && + tk2.accepts(S.token(lookahead + 2).kind); } - protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) { + protected boolean peekToken(Filter tk1, Filter tk2, Filter tk3) { return peekToken(0, tk1, tk2, tk3); } - protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2, TokenKind tk3) { - return S.token(lookahead + 1).kind == tk1 && - S.token(lookahead + 2).kind == tk2 && - S.token(lookahead + 3).kind == tk3; + protected boolean peekToken(int lookahead, Filter tk1, Filter tk2, Filter tk3) { + return tk1.accepts(S.token(lookahead + 1).kind) && + tk2.accepts(S.token(lookahead + 2).kind) && + tk3.accepts(S.token(lookahead + 3).kind); } - protected boolean peekToken(TokenKind... kinds) { + @SuppressWarnings("unchecked") + protected boolean peekToken(Filter... kinds) { return peekToken(0, kinds); } - protected boolean peekToken(int lookahead, TokenKind... kinds) { + @SuppressWarnings("unchecked") + protected boolean peekToken(int lookahead, Filter... kinds) { for (; lookahead < kinds.length ; lookahead++) { - if (S.token(lookahead + 1).kind != kinds[lookahead]) { + if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) { return false; } } @@ -333,6 +388,7 @@ public class JavacParser implements Parser { if (stopAtMemberDecl) return; break; + case UNDERSCORE: case IDENTIFIER: if (stopAtIdentifier) return; @@ -552,21 +608,45 @@ public class JavacParser implements Parser { nextToken(); return name; } + } else if (token.kind == THIS) { + if (allowThisIdent) { + // Make sure we're using a supported source version. + checkTypeAnnotations(); + Name name = token.name(); + nextToken(); + return name; + } else { + error(token.pos, "this.as.identifier"); + nextToken(); + return names.error; + } + } else if (token.kind == UNDERSCORE) { + warning(token.pos, "underscore.as.identifier"); + Name name = token.name(); + nextToken(); + return name; } else { accept(IDENTIFIER); return names.error; } -} + } /** - * Qualident = Ident { DOT Ident } + * Qualident = Ident { DOT [Annotations] Ident } */ - public JCExpression qualident() { + public JCExpression qualident(boolean allowAnnos) { JCExpression t = toP(F.at(token.pos).Ident(ident())); while (token.kind == DOT) { int pos = token.pos; nextToken(); + List tyannos = null; + if (allowAnnos) { + tyannos = typeAnnotationsOpt(); + } t = toP(F.at(pos).Select(t, ident())); + if (tyannos != null && tyannos.nonEmpty()) { + t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); + } } return t; } @@ -675,7 +755,7 @@ public class JavacParser implements Parser { nextToken(); return t; } -//where + //where boolean isZero(String s) { char[] cs = s.toCharArray(); int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10); @@ -695,7 +775,34 @@ public class JavacParser implements Parser { return term(EXPR); } + /** + * parses (optional) type annotations followed by a type. If the + * annotations are present before the type and are not consumed during array + * parsing, this method returns a {@link JCAnnotatedType} consisting of + * these annotations and the underlying type. Otherwise, it returns the + * underlying type. + * + *

+ * + * Note that this method sets {@code mode} to {@code TYPE} first, before + * parsing annotations. + */ public JCExpression parseType() { + List annotations = typeAnnotationsOpt(); + return parseType(annotations); + } + + public JCExpression parseType(List annotations) { + JCExpression result = unannotatedType(); + + if (annotations.nonEmpty()) { + result = insertAnnotationsToMostInner(result, annotations, false); + } + + return result; + } + + public JCExpression unannotatedType() { return term(TYPE); } @@ -853,7 +960,7 @@ public class JavacParser implements Parser { opStackSupply.add(opStack); return t; } -//where + //where /** Construct a binary or type test node. */ private JCExpression makeOp(int pos, @@ -932,9 +1039,9 @@ public class JavacParser implements Parser { * | NEW [TypeArguments] Creator * | "(" Arguments ")" "->" ( Expression | Block ) * | Ident "->" ( Expression | Block ) - * | Ident { "." Ident } + * | [Annotations] Ident { "." [Annotations] Ident } * | Expression3 MemberReferenceSuffix - * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) + * [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) * | Arguments * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) * ] @@ -1056,7 +1163,35 @@ public class JavacParser implements Parser { typeArgs = null; } else return illegal(); break; - case IDENTIFIER: case ASSERT: case ENUM: + case MONKEYS_AT: + // Only annotated cast types are valid + List typeAnnos = typeAnnotationsOpt(); + if (typeAnnos.isEmpty()) { + // else there would be no '@' + throw new AssertionError("Expected type annotations, but found none!"); + } + + JCExpression expr = term3(); + + if ((mode & TYPE) == 0) { + // Type annotations on class literals no longer legal + if (!expr.hasTag(Tag.SELECT)) { + return illegal(typeAnnos.head.pos); + } + JCFieldAccess sel = (JCFieldAccess)expr; + + if (sel.name != names._class) { + return illegal(); + } else { + log.error(token.pos, "no.annotations.on.dot.class"); + return expr; + } + } else { + // Type annotations targeting a cast + t = insertAnnotationsToMostInner(expr, typeAnnos, false); + } + break; + case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM: if (typeArgs != null) return illegal(); if ((mode & EXPR) != 0 && peekToken(ARROW)) { t = lambdaExpressionOrStatement(false, false, pos); @@ -1064,6 +1199,13 @@ public class JavacParser implements Parser { t = toP(F.at(token.pos).Ident(ident())); loop: while (true) { pos = token.pos; + final List annos = typeAnnotationsOpt(); + + // need to report an error later if LBRACKET is for array + // index access rather than array creation level + if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS) + return illegal(annos.head.pos); + switch (token.kind) { case LBRACKET: nextToken(); @@ -1071,11 +1213,23 @@ public class JavacParser implements Parser { nextToken(); t = bracketsOpt(t); t = toP(F.at(pos).TypeArray(t)); - t = bracketsSuffix(t); + if (annos.nonEmpty()) { + t = toP(F.at(pos).AnnotatedType(annos, t)); + } + // .class is only allowed if there were no annotations + JCExpression nt = bracketsSuffix(t); + if (nt != t && (annos.nonEmpty() || TreeInfo.containsTypeAnnotation(t))) { + // t and nt are different if bracketsSuffix parsed a .class. + // The check for nonEmpty covers the case when the whole array is annotated. + // Helper method isAnnotated looks for annos deeply within t. + syntaxError("no.annotations.on.dot.class"); + } + t = nt; } else { if ((mode & EXPR) != 0) { mode = EXPR; JCExpression t1 = term(); + if (!annos.isEmpty()) t = illegal(annos.head.pos); t = to(F.at(pos).Indexed(t, t1)); } accept(RBRACKET); @@ -1085,6 +1239,7 @@ public class JavacParser implements Parser { if ((mode & EXPR) != 0) { mode = EXPR; t = arguments(typeArgs, t); + if (!annos.isEmpty()) t = illegal(annos.head.pos); typeArgs = null; } break loop; @@ -1125,9 +1280,25 @@ public class JavacParser implements Parser { break loop; } } + + List tyannos = null; + if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) { + tyannos = typeAnnotationsOpt(); + } // typeArgs saved for next loop iteration. t = toP(F.at(pos).Select(t, ident())); + if (tyannos != null && tyannos.nonEmpty()) { + t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); + } break; + case ELLIPSIS: + if (this.permitTypeAnnotationsPushBack) { + this.typeAnnotationsPushedBack = annos; + } else if (annos.nonEmpty()) { + // Don't return here -- error recovery attempt + illegal(annos.head.pos); + } + break loop; case LT: if ((mode & TYPE) == 0 && isUnboundMemberRef()) { //this is an unbound method reference whose qualifier @@ -1201,6 +1372,8 @@ public class JavacParser implements Parser { if (typeArgs != null) illegal(); while (true) { int pos1 = token.pos; + final List annos = typeAnnotationsOpt(); + if (token.kind == LBRACKET) { nextToken(); if ((mode & TYPE) != 0) { @@ -1214,6 +1387,9 @@ public class JavacParser implements Parser { mode = EXPR; continue; } + if (annos.nonEmpty()) { + t = toP(F.at(pos1).AnnotatedType(annos, t)); + } return t; } mode = oldmode; @@ -1242,7 +1418,15 @@ public class JavacParser implements Parser { t = innerCreator(pos2, typeArgs, t); typeArgs = null; } else { + List tyannos = null; + if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) { + // is the mode check needed? + tyannos = typeAnnotationsOpt(); + } t = toP(F.at(pos1).Select(t, ident())); + if (tyannos != null && tyannos.nonEmpty()) { + t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); + } t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); typeArgs = null; } @@ -1252,6 +1436,12 @@ public class JavacParser implements Parser { accept(COLCOL); t = memberReferenceSuffix(pos1, t); } else { + if (!annos.isEmpty()) { + if (permitTypeAnnotationsPushBack) + typeAnnotationsPushedBack = annos; + else + return illegal(annos.head.pos); + } break; } } @@ -1274,7 +1464,7 @@ public class JavacParser implements Parser { int pos = 0, depth = 0; for (Token t = S.token(pos) ; ; t = S.token(++pos)) { switch (t.kind) { - case IDENTIFIER: case QUES: case EXTENDS: case SUPER: + case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER: case DOT: case RBRACKET: case LBRACKET: case COMMA: case BYTE: case SHORT: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case CHAR: @@ -1310,7 +1500,7 @@ public class JavacParser implements Parser { ParensResult analyzeParens() { int depth = 0; boolean type = false; - for (int lookahead = 0 ; ; lookahead++) { + outer: for (int lookahead = 0 ; ; lookahead++) { TokenKind tk = S.token(lookahead).kind; switch (tk) { case EXTENDS: case SUPER: case COMMA: @@ -1323,8 +1513,8 @@ public class JavacParser implements Parser { if (peekToken(lookahead, RPAREN)) { //Type, ')' -> cast return ParensResult.CAST; - } else if (peekToken(lookahead, IDENTIFIER)) { - //Type, 'Identifier -> explicit lambda + } else if (peekToken(lookahead, LAX_IDENTIFIER)) { + //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; } break; @@ -1350,16 +1540,19 @@ public class JavacParser implements Parser { case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: case TRUE: case FALSE: case NULL: - case NEW: case IDENTIFIER: case ASSERT: case ENUM: + case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE: case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: return ParensResult.CAST; default: return ParensResult.PARENS; } + case UNDERSCORE: + case ASSERT: + case ENUM: case IDENTIFIER: - if (peekToken(lookahead, IDENTIFIER)) { - // Identifier, Identifier -> explicit lambda + if (peekToken(lookahead, LAX_IDENTIFIER)) { + // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; } else if (peekToken(lookahead, RPAREN, ARROW)) { // Identifier, ')' '->' -> implicit lambda @@ -1368,12 +1561,39 @@ public class JavacParser implements Parser { break; case FINAL: case ELLIPSIS: - case MONKEYS_AT: //those can only appear in explicit lambdas return ParensResult.EXPLICIT_LAMBDA; + case MONKEYS_AT: + type = true; + lookahead += 1; //skip '@' + while (peekToken(lookahead, DOT)) { + lookahead += 2; + } + if (peekToken(lookahead, LPAREN)) { + lookahead++; + //skip annotation values + int nesting = 0; + for (; ; lookahead++) { + TokenKind tk2 = S.token(lookahead).kind; + switch (tk2) { + case EOF: + return ParensResult.PARENS; + case LPAREN: + nesting++; + break; + case RPAREN: + nesting--; + if (nesting == 0) { + continue outer; + } + break; + } + } + } + break; case LBRACKET: - if (peekToken(lookahead, RBRACKET, IDENTIFIER)) { - // '[', ']', Identifier -> explicit lambda + if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) { + // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; } else if (peekToken(lookahead, RBRACKET, RPAREN) || peekToken(lookahead, RBRACKET, AMP)) { @@ -1402,11 +1622,11 @@ public class JavacParser implements Parser { // '>', ')' -> cast // '>', '&' -> cast return ParensResult.CAST; - } else if (peekToken(lookahead, IDENTIFIER, COMMA) || - peekToken(lookahead, IDENTIFIER, RPAREN, ARROW) || + } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) || + peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) || peekToken(lookahead, ELLIPSIS)) { - // '>', Identifier, ',' -> explicit lambda - // '>', Identifier, ')', '->' -> explicit lambda + // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda + // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda // '>', '...' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; } @@ -1426,6 +1646,13 @@ public class JavacParser implements Parser { } } + /** Accepts all identifier-like tokens */ + Filter LAX_IDENTIFIER = new Filter() { + public boolean accepts(TokenKind t) { + return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM; + } + }; + enum ParensResult { CAST, EXPLICIT_LAMBDA, @@ -1433,21 +1660,9 @@ public class JavacParser implements Parser { PARENS; } - JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) { - ListBuffer params = new ListBuffer(); - params.append(firstParam); - JCVariableDecl lastParam = firstParam; - while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { - nextToken(); - params.append(lastParam = formalParameter()); - } - accept(RPAREN); - return lambdaExpressionOrStatementRest(params.toList(), pos); - } - JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) { List params = explicitParams ? - formalParameters() : + formalParameters(true) : implicitParameters(hasParens); return lambdaExpressionOrStatementRest(params, pos); @@ -1609,37 +1824,43 @@ public class JavacParser implements Parser { /** * {@literal * TypeArgument = Type - * | "?" - * | "?" EXTENDS Type {"&" Type} - * | "?" SUPER Type + * | [Annotations] "?" + * | [Annotations] "?" EXTENDS Type {"&" Type} + * | [Annotations] "?" SUPER Type * } */ JCExpression typeArgument() { - if (token.kind != QUES) return parseType(); + List annotations = typeAnnotationsOpt(); + if (token.kind != QUES) return parseType(annotations); int pos = token.pos; nextToken(); + JCExpression result; if (token.kind == EXTENDS) { TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); nextToken(); JCExpression bound = parseType(); - return F.at(pos).Wildcard(t, bound); + result = F.at(pos).Wildcard(t, bound); } else if (token.kind == SUPER) { TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); nextToken(); JCExpression bound = parseType(); - return F.at(pos).Wildcard(t, bound); - } else if (token.kind == IDENTIFIER) { + result = F.at(pos).Wildcard(t, bound); + } else if (LAX_IDENTIFIER.accepts(token.kind)) { //error recovery TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); JCExpression wc = toP(F.at(pos).Wildcard(t, null)); JCIdent id = toP(F.at(token.pos).Ident(ident())); JCErroneous err = F.at(pos).Erroneous(List.of(wc, id)); reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER); - return err; + result = err; } else { TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); - return toP(F.at(pos).Wildcard(t, null)); + result = toP(F.at(pos).Wildcard(t, null)); } + if (!annotations.isEmpty()) { + result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result)); + } + return result; } JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) { @@ -1648,22 +1869,51 @@ public class JavacParser implements Parser { return toP(F.at(pos).TypeApply(t, args)); } - /** BracketsOpt = {"[" "]"} + /** + * BracketsOpt = { [Annotations] "[" "]" }* + * + *

+ * + * annotations is the list of annotations targeting + * the expression t. */ - private JCExpression bracketsOpt(JCExpression t) { + private JCExpression bracketsOpt(JCExpression t, + List annotations) { + List nextLevelAnnotations = typeAnnotationsOpt(); + if (token.kind == LBRACKET) { int pos = token.pos; nextToken(); - t = bracketsOptCont(t, pos); - F.at(pos); + t = bracketsOptCont(t, pos, nextLevelAnnotations); + } else if (!nextLevelAnnotations.isEmpty()) { + if (permitTypeAnnotationsPushBack) { + this.typeAnnotationsPushedBack = nextLevelAnnotations; + } else { + return illegal(nextLevelAnnotations.head.pos); + } + } + + if (!annotations.isEmpty()) { + t = toP(F.at(token.pos).AnnotatedType(annotations, t)); } return t; } - private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) { + /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ] + */ + private JCExpression bracketsOpt(JCExpression t) { + return bracketsOpt(t, List.nil()); + } + + private JCExpression bracketsOptCont(JCExpression t, int pos, + List annotations) { accept(RBRACKET); t = bracketsOpt(t); - return toP(F.at(pos).TypeArray(t)); + t = toP(F.at(pos).TypeArray(t)); + if (annotations.nonEmpty()) { + t = toP(F.at(pos).AnnotatedType(annotations, t)); + } + return t; } /** BracketsSuffixExpr = "." CLASS @@ -1677,8 +1927,8 @@ public class JavacParser implements Parser { accept(CLASS); if (token.pos == endPosTable.errorEndPos) { // error recovery - Name name = null; - if (token.kind == IDENTIFIER) { + Name name; + if (LAX_IDENTIFIER.accepts(token.kind)) { name = token.name(); nextToken(); } else { @@ -1715,8 +1965,8 @@ public class JavacParser implements Parser { if (token.kind == LT) { typeArgs = typeArguments(false); } - Name refName = null; - ReferenceMode refMode = null; + Name refName; + ReferenceMode refMode; if (token.kind == NEW) { refMode = ReferenceMode.NEW; refName = names.init; @@ -1728,18 +1978,31 @@ public class JavacParser implements Parser { return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs)); } - /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) + /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) */ JCExpression creator(int newpos, List typeArgs) { + List newAnnotations = typeAnnotationsOpt(); + switch (token.kind) { case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: - if (typeArgs == null) - return arrayCreatorRest(newpos, basicType()); + if (typeArgs == null) { + if (newAnnotations.isEmpty()) { + return arrayCreatorRest(newpos, basicType()); + } else { + return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType()))); + } + } break; default: } - JCExpression t = qualident(); + JCExpression t = qualident(true); + + // handle type annotations for non primitive arrays + if (newAnnotations.nonEmpty()) { + t = insertAnnotationsToMostInner(t, newAnnotations, false); + } + int oldmode = mode; mode = TYPE; boolean diamondFound = false; @@ -1757,7 +2020,13 @@ public class JavacParser implements Parser { } int pos = token.pos; nextToken(); + List tyannos = typeAnnotationsOpt(); t = toP(F.at(pos).Select(t, ident())); + + if (tyannos != null && tyannos.nonEmpty()) { + t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t)); + } + if (token.kind == LT) { lastTypeargsPos = token.pos; checkGenerics(); @@ -1766,7 +2035,7 @@ public class JavacParser implements Parser { } } mode = oldmode; - if (token.kind == LBRACKET) { + if (token.kind == LBRACKET || token.kind == MONKEYS_AT) { JCExpression e = arrayCreatorRest(newpos, t); if (diamondFound) { reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond"); @@ -1787,7 +2056,15 @@ public class JavacParser implements Parser { } return e; } else if (token.kind == LPAREN) { - return classCreatorRest(newpos, null, typeArgs, t); + JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t); + if (newClass.def != null) { + assert newClass.def.mods.annotations.isEmpty(); + if (newAnnotations.nonEmpty()) { + newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos); + newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations); + } + } + return newClass; } else { setErrorEndPos(token.pos); reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET); @@ -1796,10 +2073,17 @@ public class JavacParser implements Parser { } } - /** InnerCreator = Ident [TypeArguments] ClassCreatorRest + /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest */ JCExpression innerCreator(int newpos, List typeArgs, JCExpression encl) { + List newAnnotations = typeAnnotationsOpt(); + JCExpression t = toP(F.at(token.pos).Ident(ident())); + + if (newAnnotations.nonEmpty()) { + t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t)); + } + if (token.kind == LT) { int oldmode = mode; checkGenerics(); @@ -1809,35 +2093,65 @@ public class JavacParser implements Parser { return classCreatorRest(newpos, encl, typeArgs, t); } - /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer - * | Expression "]" {"[" Expression "]"} BracketsOpt ) + /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer + * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt ) */ JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { + List annos = typeAnnotationsOpt(); + accept(LBRACKET); if (token.kind == RBRACKET) { accept(RBRACKET); - elemtype = bracketsOpt(elemtype); + elemtype = bracketsOpt(elemtype, annos); if (token.kind == LBRACE) { - return arrayInitializer(newpos, elemtype); + JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype); + if (annos.nonEmpty()) { + // when an array initializer is present then + // the parsed annotations should target the + // new array tree + // bracketsOpt inserts the annotation in + // elemtype, and it needs to be corrected + // + JCAnnotatedType annotated = (JCAnnotatedType)elemtype; + assert annotated.annotations == annos; + na.annotations = annotated.annotations; + na.elemtype = annotated.underlyingType; + } + return na; } else { JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.nil(), null)); return syntaxError(token.pos, List.of(t), "array.dimension.missing"); } } else { ListBuffer dims = new ListBuffer(); + + // maintain array dimension type annotations + ListBuffer> dimAnnotations = ListBuffer.lb(); + dimAnnotations.append(annos); + dims.append(parseExpression()); accept(RBRACKET); - while (token.kind == LBRACKET) { + while (token.kind == LBRACKET + || token.kind == MONKEYS_AT) { + List maybeDimAnnos = typeAnnotationsOpt(); int pos = token.pos; nextToken(); if (token.kind == RBRACKET) { - elemtype = bracketsOptCont(elemtype, pos); + elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); } else { - dims.append(parseExpression()); - accept(RBRACKET); + if (token.kind == RBRACKET) { // no dimension + elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos); + } else { + dimAnnotations.append(maybeDimAnnos); + dims.append(parseExpression()); + accept(RBRACKET); + } } } - return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); + + JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); + na.dimAnnotations = dimAnnotations.toList(); + return na; } } @@ -2026,10 +2340,7 @@ public class JavacParser implements Parser { nextToken(); JCStatement stat = parseStatement(); return List.of(F.at(pos).Labelled(prevToken.name(), stat)); - } else if ((lastmode & TYPE) != 0 && - (token.kind == IDENTIFIER || - token.kind == ASSERT || - token.kind == ENUM)) { + } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { pos = token.pos; JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); F.at(pos); @@ -2183,14 +2494,14 @@ public class JavacParser implements Parser { } case BREAK: { nextToken(); - Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; + Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null; JCBreak t = to(F.at(pos).Break(label)); accept(SEMI); return t; } case CONTINUE: { nextToken(); - Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; + Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null; JCContinue t = to(F.at(pos).Continue(label)); accept(SEMI); return t; @@ -2248,6 +2559,7 @@ public class JavacParser implements Parser { } /** CatchClause = CATCH "(" FormalParameter ")" Block + * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below. */ protected JCCatch catchClause() { int pos = token.pos; @@ -2270,7 +2582,9 @@ public class JavacParser implements Parser { while (token.kind == BAR) { checkMulticatch(); nextToken(); - catchTypes.add(qualident()); + // Instead of qualident this is now parseType. + // But would that allow too much, e.g. arrays or generics? + catchTypes.add(parseType()); } return catchTypes.toList(); } @@ -2351,9 +2665,7 @@ public class JavacParser implements Parser { return variableDeclarators(optFinal(0), parseType(), stats).toList(); } else { JCExpression t = term(EXPR | TYPE); - if ((lastmode & TYPE) != 0 && - (token.kind == IDENTIFIER || token.kind == ASSERT || - token.kind == ENUM)) { + if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) { return variableDeclarators(modifiersOpt(), t, stats).toList(); } else if ((lastmode & TYPE) != 0 && token.kind == COLON) { error(pos, "bad.initializer", "for-loop"); @@ -2373,16 +2685,28 @@ public class JavacParser implements Parser { } /** AnnotationsOpt = { '@' Annotation } + * + * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION */ - List annotationsOpt() { + List annotationsOpt(Tag kind) { if (token.kind != MONKEYS_AT) return List.nil(); // optimization ListBuffer buf = new ListBuffer(); + int prevmode = mode; while (token.kind == MONKEYS_AT) { int pos = token.pos; nextToken(); - buf.append(annotation(pos)); + buf.append(annotation(pos, kind)); } - return buf.toList(); + lastmode = mode; + mode = prevmode; + List annotations = buf.toList(); + + return annotations; + } + + List typeAnnotationsOpt() { + List annotations = annotationsOpt(Tag.TYPE_ANNOTATION); + return annotations; } /** ModifiersOpt = { Modifier } @@ -2408,7 +2732,7 @@ public class JavacParser implements Parser { if (token.deprecatedFlag()) { flags |= Flags.DEPRECATED; } - int lastPos = Position.NOPOS; + int lastPos; loop: while (true) { long flag; @@ -2435,12 +2759,11 @@ public class JavacParser implements Parser { if (flag == Flags.ANNOTATION) { checkAnnotations(); if (token.kind != INTERFACE) { - JCAnnotation ann = annotation(lastPos); + JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION); // if first modifier is an annotation, set pos to annotation's. if (flags == 0 && annotations.isEmpty()) pos = ann.pos; annotations.append(ann); - lastPos = ann.pos; flag = 0; } } @@ -2464,14 +2787,27 @@ public class JavacParser implements Parser { } /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] + * * @param pos position of "@" token + * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION */ - JCAnnotation annotation(int pos) { + JCAnnotation annotation(int pos, Tag kind) { // accept(AT); // AT consumed by caller checkAnnotations(); - JCTree ident = qualident(); + if (kind == Tag.TYPE_ANNOTATION) { + checkTypeAnnotations(); + } + JCTree ident = qualident(false); List fieldValues = annotationFieldValuesOpt(); - JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); + JCAnnotation ann; + if (kind == Tag.ANNOTATION) { + ann = F.at(pos).Annotation(ident, fieldValues); + } else if (kind == Tag.TYPE_ANNOTATION) { + ann = F.at(pos).TypeAnnotation(ident, fieldValues); + } else { + throw new AssertionError("Unhandled annotation kind: " + kind); + } + storeEnd(ann, S.prevToken().endPos); return ann; } @@ -2524,7 +2860,7 @@ public class JavacParser implements Parser { case MONKEYS_AT: pos = token.pos; nextToken(); - return annotation(pos); + return annotation(pos, Tag.ANNOTATION); case LBRACE: pos = token.pos; accept(LBRACE); @@ -2609,8 +2945,18 @@ public class JavacParser implements Parser { /** VariableDeclaratorId = Ident BracketsOpt */ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { + return variableDeclaratorId(mods, type, false); + } + //where + JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) { int pos = token.pos; - Name name = ident(); + Name name; + if (lambdaParameter && token.kind == UNDERSCORE) { + syntaxError(pos, "expected", IDENTIFIER); + name = token.name(); + } else { + name = ident(); + } if ((mods.flags & Flags.VARARGS) != 0 && token.kind == LBRACKET) { log.error(token.pos, "varargs.and.old.array.syntax"); @@ -2669,7 +3015,7 @@ public class JavacParser implements Parser { mods = null; } nextToken(); - pid = qualident(); + pid = qualident(false); accept(SEMI); } ListBuffer defs = new ListBuffer(); @@ -2770,7 +3116,7 @@ public class JavacParser implements Parser { } else { int pos = token.pos; List errs; - if (token.kind == IDENTIFIER) { + if (LAX_IDENTIFIER.accepts(token.kind)) { errs = List.of(mods, toP(F.at(pos).Ident(ident()))); setErrorEndPos(token.pos); } else { @@ -2787,7 +3133,7 @@ public class JavacParser implements Parser { } int pos = token.pos; List errs; - if (token.kind == IDENTIFIER) { + if (LAX_IDENTIFIER.accepts(token.kind)) { errs = List.of(mods, toP(F.at(pos).Ident(ident()))); setErrorEndPos(token.pos); } else { @@ -2920,7 +3266,7 @@ public class JavacParser implements Parser { flags |= Flags.DEPRECATED; } int pos = token.pos; - List annotations = annotationsOpt(); + List annotations = annotationsOpt(Tag.ANNOTATION); JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); List typeArgs = typeArgumentsOpt(); int identPos = token.pos; @@ -3023,15 +3369,25 @@ public class JavacParser implements Parser { mods.pos = pos; storeEnd(mods, pos); } + List annosAfterParams = annotationsOpt(Tag.ANNOTATION); + Token tk = token; pos = token.pos; JCExpression type; boolean isVoid = token.kind == VOID; if (isVoid) { + if (annosAfterParams.nonEmpty()) + illegal(annosAfterParams.head.pos); type = to(F.at(pos).TypeIdent(TypeTag.VOID)); nextToken(); } else { - type = parseType(); + if (annosAfterParams.nonEmpty()) { + mods.annotations = mods.annotations.appendList(annosAfterParams); + if (mods.pos == Position.NOPOS) + mods.pos = mods.annotations.head.pos; + } + // method returns types are un-annotated types + type = unannotatedType(); } if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) { if (isInterface || tk.name() != className) @@ -3084,51 +3440,71 @@ public class JavacParser implements Parser { List typarams, boolean isInterface, boolean isVoid, Comment dc) { - List params = formalParameters(); - if (!isVoid) type = bracketsOpt(type); - List thrown = List.nil(); - if (token.kind == THROWS) { - nextToken(); - thrown = qualidentList(); + if (isInterface && (mods.flags & Flags.STATIC) != 0) { + checkStaticInterfaceMethods(); } - JCBlock body = null; - JCExpression defaultValue; - if (token.kind == LBRACE) { - body = block(); - defaultValue = null; - } else { - if (token.kind == DEFAULT) { - accept(DEFAULT); - defaultValue = annotationValue(); - } else { - defaultValue = null; + JCVariableDecl prevReceiverParam = this.receiverParam; + try { + this.receiverParam = null; + // Parsing formalParameters sets the receiverParam, if present + List params = formalParameters(); + if (!isVoid) type = bracketsOpt(type); + List thrown = List.nil(); + if (token.kind == THROWS) { + nextToken(); + thrown = qualidentList(); } - accept(SEMI); - if (token.pos <= endPosTable.errorEndPos) { - // error recovery - skip(false, true, false, false); - if (token.kind == LBRACE) { - body = block(); + JCBlock body = null; + JCExpression defaultValue; + if (token.kind == LBRACE) { + body = block(); + defaultValue = null; + } else { + if (token.kind == DEFAULT) { + accept(DEFAULT); + defaultValue = annotationValue(); + } else { + defaultValue = null; + } + accept(SEMI); + if (token.pos <= endPosTable.errorEndPos) { + // error recovery + skip(false, true, false, false); + if (token.kind == LBRACE) { + body = block(); + } } } - } - JCMethodDecl result = - toP(F.at(pos).MethodDef(mods, name, type, typarams, - params, thrown, - body, defaultValue)); - attach(result, dc); - return result; + JCMethodDecl result = + toP(F.at(pos).MethodDef(mods, name, type, typarams, + receiverParam, params, thrown, + body, defaultValue)); + attach(result, dc); + return result; + } finally { + this.receiverParam = prevReceiverParam; + } } - /** QualidentList = Qualident {"," Qualident} + /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident} */ List qualidentList() { ListBuffer ts = new ListBuffer(); - ts.append(qualident()); + + List typeAnnos = typeAnnotationsOpt(); + if (!typeAnnos.isEmpty()) + ts.append(toP(F.at(typeAnnos.head.pos).AnnotatedType(typeAnnos, qualident(true)))); + else + ts.append(qualident(true)); while (token.kind == COMMA) { nextToken(); - ts.append(qualident()); + + typeAnnos = typeAnnotationsOpt(); + if (!typeAnnos.isEmpty()) + ts.append(toP(F.at(typeAnnos.head.pos).AnnotatedType(typeAnnos, qualident(true)))); + else + ts.append(qualident(true)); } return ts.toList(); } @@ -3157,13 +3533,14 @@ public class JavacParser implements Parser { /** * {@literal - * TypeParameter = TypeVariable [TypeParameterBound] + * TypeParameter = [Annotations] TypeVariable [TypeParameterBound] * TypeParameterBound = EXTENDS Type {"&" Type} * TypeVariable = Ident * } */ JCTypeParameter typeParameter() { int pos = token.pos; + List annos = typeAnnotationsOpt(); Name name = ident(); ListBuffer bounds = new ListBuffer(); if (token.kind == EXTENDS) { @@ -3174,7 +3551,7 @@ public class JavacParser implements Parser { bounds.append(parseType()); } } - return toP(F.at(pos).TypeParameter(name, bounds.toList())); + return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos)); } /** FormalParameters = "(" [ FormalParameterList ] ")" @@ -3182,14 +3559,24 @@ public class JavacParser implements Parser { * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter */ List formalParameters() { + return formalParameters(false); + } + List formalParameters(boolean lambdaParameters) { ListBuffer params = new ListBuffer(); - JCVariableDecl lastParam = null; + JCVariableDecl lastParam; accept(LPAREN); if (token.kind != RPAREN) { - params.append(lastParam = formalParameter()); + this.allowThisIdent = true; + lastParam = formalParameter(lambdaParameters); + if (lastParam.name.contentEquals(TokenKind.THIS.name)) { + this.receiverParam = lastParam; + } else { + params.append(lastParam); + } + this.allowThisIdent = false; while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { nextToken(); - params.append(lastParam = formalParameter()); + params.append(lastParam = formalParameter(lambdaParameters)); } } accept(RPAREN); @@ -3221,24 +3608,113 @@ public class JavacParser implements Parser { return mods; } + /** + * Inserts the annotations (and possibly a new array level) + * to the left-most type in an array or nested type. + * + * When parsing a type like {@code @B Outer.Inner @A []}, the + * {@code @A} annotation should target the array itself, while + * {@code @B} targets the nested type {@code Outer}. + * + * Currently the parser parses the annotation first, then + * the array, and then inserts the annotation to the left-most + * nested type. + * + * When {@code createNewLevel} is true, then a new array + * level is inserted as the most inner type, and have the + * annotations target it. This is useful in the case of + * varargs, e.g. {@code String @A [] @B ...}, as the parser + * first parses the type {@code String @A []} then inserts + * a new array level with {@code @B} annotation. + */ + private JCExpression insertAnnotationsToMostInner( + JCExpression type, List annos, + boolean createNewLevel) { + int origEndPos = getEndPos(type); + JCExpression mostInnerType = type; + JCArrayTypeTree mostInnerArrayType = null; + while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) { + mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType); + mostInnerType = mostInnerArrayType.elemtype; + } + + if (createNewLevel) { + mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType)); + } + + JCExpression mostInnerTypeToReturn = mostInnerType; + if (annos.nonEmpty()) { + JCExpression lastToModify = mostInnerType; + + while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) || + TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) { + while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) { + lastToModify = mostInnerType; + mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression(); + } + while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) { + lastToModify = mostInnerType; + mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz; + } + } + + mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType); + + if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) { + ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType; + } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) { + ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType; + } else { + // We never saw a SELECT or TYPEAPPLY, return the annotated type. + mostInnerTypeToReturn = mostInnerType; + } + } + + if (mostInnerArrayType == null) { + return mostInnerTypeToReturn; + } else { + mostInnerArrayType.elemtype = mostInnerTypeToReturn; + storeEnd(type, origEndPos); + return type; + } + } + /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter */ protected JCVariableDecl formalParameter() { + return formalParameter(false); + } + protected JCVariableDecl formalParameter(boolean lambdaParameter) { JCModifiers mods = optFinal(Flags.PARAMETER); + // need to distinguish between vararg annos and array annos + // look at typeAnnotationsPushedBack comment + this.permitTypeAnnotationsPushBack = true; JCExpression type = parseType(); + this.permitTypeAnnotationsPushBack = false; + if (token.kind == ELLIPSIS) { + List varargsAnnos = typeAnnotationsPushedBack; + typeAnnotationsPushedBack = List.nil(); checkVarargs(); mods.flags |= Flags.VARARGS; - type = to(F.at(token.pos).TypeArray(type)); + // insert var arg type annotations + type = insertAnnotationsToMostInner(type, varargsAnnos, true); nextToken(); + } else { + // if not a var arg, then typeAnnotationsPushedBack should be null + if (typeAnnotationsPushedBack.nonEmpty()) { + reportSyntaxError(typeAnnotationsPushedBack.head.pos, + "illegal.start.of.type"); + } + typeAnnotationsPushedBack = List.nil(); } - return variableDeclaratorId(mods, type); + return variableDeclaratorId(mods, type, lambdaParameter); } protected JCVariableDecl implicitParameter() { JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); - return variableDeclaratorId(mods, null); + return variableDeclaratorId(mods, null, true); } /* ---------- auxiliary methods -------------- */ @@ -3479,6 +3955,18 @@ public class JavacParser implements Parser { allowIntersectionTypesInCast = true; } } + void checkStaticInterfaceMethods() { + if (!allowStaticInterfaceMethods) { + log.error(token.pos, "static.intf.methods.not.supported.in.source", source.name); + allowStaticInterfaceMethods = true; + } + } + void checkTypeAnnotations() { + if (!allowTypeAnnotations) { + log.error(token.pos, "type.annotations.not.supported.in.source", source.name); + allowTypeAnnotations = true; + } + } /* * a functional source tree and end position mappings diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java index d52a62ef704..847a42b17c8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -236,7 +236,7 @@ public class JavadocTokenizer extends JavaTokenizer { // relative to the best match found in the array. if (pos == Position.NOPOS) return Position.NOPOS; - if (pos < 0 || pos >= docComment.length()) + if (pos < 0 || pos > docComment.length()) throw new StringIndexOutOfBoundsException(String.valueOf(pos)); if (docPosns == null) return Position.NOPOS; diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java index 20c49e6cfc2..8a813f0e9de 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -59,6 +59,7 @@ public class Scanner implements Lexer { private List savedTokens = new ArrayList(); private JavaTokenizer tokenizer; + /** * Create a scanner from the input array. This method might * modify the array. To avoid copying the input array, ensure diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java index 3e6362aa8e3..d55defedf73 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java @@ -33,6 +33,7 @@ import com.sun.tools.javac.parser.Tokens.Token.Tag; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Filter; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Names; @@ -74,7 +75,6 @@ public class Tokens { protected Tokens(Context context) { context.put(tokensKey, this); names = Names.instance(context); - for (TokenKind t : TokenKind.values()) { if (t.name != null) enterKeyword(t.name, t); @@ -113,7 +113,7 @@ public class Tokens { * This enum defines all tokens used by the javac scanner. A token is * optionally associated with a name. */ - public enum TokenKind implements Formattable { + public enum TokenKind implements Formattable, Filter { EOF(), ERROR(), IDENTIFIER(Tag.NAMED), @@ -176,6 +176,7 @@ public class Tokens { TRUE("true", Tag.NAMED), FALSE("false", Tag.NAMED), NULL("null", Tag.NAMED), + UNDERSCORE("_", Tag.NAMED), ARROW("->"), COLCOL("::"), LPAREN("("), @@ -283,6 +284,11 @@ public class Tokens { public String toString(Locale locale, Messages messages) { return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString()); } + + @Override + public boolean accepts(TokenKind that) { + return this == that; + } } public interface Comment { diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java index 84e6792cdd1..8b308c5834a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -38,7 +38,7 @@ import static com.sun.tools.javac.util.LayoutCharacters.*; /** The char reader used by the javac lexer/tokenizer. Returns the sequence of * characters contained in the input stream, handling unicode escape accordingly. - * Additionally, it provide features for saving chars into a buffer and to retrieve + * Additionally, it provides features for saving chars into a buffer and to retrieve * them at a later stage. * *

This is NOT part of any supported API. diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 498ca34b415..d71184d5157 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -817,9 +817,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea /** The set of package-info files to be processed this round. */ List packageInfoFiles; - /** The number of Messager errors generated in this round. */ - int nMessagerErrors; - /** Create a round (common code). */ private Round(Context context, int number, int priorErrors, int priorWarnings, Log.DeferredDiagnosticHandler deferredDiagnosticHandler) { @@ -829,7 +826,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea compiler = JavaCompiler.instance(context); log = Log.instance(context); log.nerrors = priorErrors; - log.nwarnings += priorWarnings; + log.nwarnings = priorWarnings; if (number == 1) { Assert.checkNonNull(deferredDiagnosticHandler); this.deferredDiagnosticHandler = deferredDiagnosticHandler; @@ -870,7 +867,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea Set newSourceFiles, Map newClassFiles) { this(prev.nextContext(), prev.number+1, - prev.nMessagerErrors, + prev.compiler.log.nerrors, prev.compiler.log.nwarnings, null); this.genClassFiles = prev.genClassFiles; @@ -911,15 +908,12 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea } /** Create the compiler to be used for the final compilation. */ - JavaCompiler finalCompiler(boolean errorStatus) { + JavaCompiler finalCompiler() { try { Context nextCtx = nextContext(); JavacProcessingEnvironment.this.context = nextCtx; JavaCompiler c = JavaCompiler.instance(nextCtx); - c.log.nwarnings += compiler.log.nwarnings; - if (errorStatus) { - c.log.nerrors += compiler.log.nerrors; - } + c.log.initRound(compiler.log); return c; } finally { compiler.close(false); @@ -1027,8 +1021,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea if (!taskListener.isEmpty()) taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); } - - nMessagerErrors = messager.errorCount(); } void showDiagnostics(boolean showAll) { @@ -1107,9 +1099,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea next.put(Tokens.tokensKey, tokens); Log nextLog = Log.instance(next); - // propogate the log's writers directly, instead of going through context - nextLog.setWriters(log); - nextLog.setSourceMap(log); + nextLog.initRound(log); JavaCompiler oldCompiler = JavaCompiler.instance(context); JavaCompiler nextCompiler = JavaCompiler.instance(next); @@ -1206,7 +1196,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea new LinkedHashSet(filer.getGeneratedSourceFileObjects()); roots = cleanTrees(round.roots); - JavaCompiler compiler = round.finalCompiler(errorStatus); + JavaCompiler compiler = round.finalCompiler(); if (newSourceFiles.size() > 0) roots = roots.appendList(compiler.parseFiles(newSourceFiles)); @@ -1311,7 +1301,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea if (procNames != null) return true; - String procPath; URL[] urls = new URL[1]; for(File pathElement : workingpath) { try { @@ -1382,6 +1371,10 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea node.sym = null; super.visitIdent(node); } + public void visitAnnotation(JCAnnotation node) { + node.attribute = null; + super.visitAnnotation(node); + } }; diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 1f36e636ccc..5161bedb3b4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -178,14 +178,23 @@ compiler.misc.no.abstracts=\ compiler.misc.incompatible.abstracts=\ multiple non-overriding abstract methods found in {0} {1} -compiler.misc.not.a.functional.intf=\ - the target type must be a functional interface +compiler.err.bad.functional.intf.anno=\ + Unexpected @FunctionalInterface annotation # 0: message segment -compiler.misc.not.a.functional.intf.1=\ - the target type must be a functional interface\n\ +compiler.err.bad.functional.intf.anno.1=\ + Unexpected @FunctionalInterface annotation\n\ {0} +# 0: symbol +compiler.misc.not.a.functional.intf=\ + {0} is not a functional interface + +# 0: symbol, 1: message segment +compiler.misc.not.a.functional.intf.1=\ + {0} is not a functional interface\n\ + {1} + # 0: symbol, 1: symbol kind, 2: symbol compiler.misc.invalid.generic.lambda.target=\ invalid functional descriptor for lambda expression\n\ @@ -319,64 +328,48 @@ compiler.err.duplicate.annotation.member.value=\ compiler.err.duplicate.annotation.missing.container=\ duplicate annotation, the declaration of {0} does not have a valid {1} annotation -# 0: type, 1: type -compiler.err.invalid.container.no.containedby=\ - invalid contained repeatable annotation, {0} is not annotated with {1} - -# 0: type, 1: type -compiler.err.invalid.container.wrong.containedby=\ - invalid contained repeatable annotation, {0} does not match {1} - -# 0: type, 1: type -compiler.err.invalid.container.no.containerfor=\ - invalid container for repeating annotations, {0} is not annotated with {1} - -# 0: type, 1: type -compiler.err.invalid.container.wrong.containerfor=\ - invalid container for repeating annotations, {0} does not match {1} +# 0: type +compiler.err.invalid.repeatable.annotation=\ + duplicate annotation, {0} is annotated with an invalid Repeatable annotation # 0: type -compiler.err.invalid.containedby.annotation=\ - duplicate annotation, {0} is annotated with an invalid ContainedBy annotation - -# 0: type -compiler.err.invalid.containedby.annotation.no.value=\ - duplicate annotation, {0} is not a valid ContainedBy, no value element method declared +compiler.err.invalid.repeatable.annotation.no.value=\ + duplicate annotation, {0} is not a valid Repeatable, no value element method declared # 0: type, 1: number -compiler.err.invalid.containedby.annotation.multiple.values=\ - duplicate annotation, {0} is not a valid ContainedBy, {1} value element methods declared +compiler.err.invalid.repeatable.annotation.multiple.values=\ + duplicate annotation, {0} is not a valid Repeatable, {1} value element methods declared # 0: type -compiler.err.invalid.containedby.annotation.invalid.value=\ - duplicate annotation, {0} is not a valid ContainedBy, invalid value element, need a method +compiler.err.invalid.repeatable.annotation.invalid.value=\ + duplicate annotation, {0} is not a valid Repeatable, invalid value element, need a method # 0: type, 1: type, 2: type -compiler.err.invalid.containedby.annotation.value.return=\ +compiler.err.invalid.repeatable.annotation.value.return=\ duplicate annotation, value element of containing annotation {0} should have type {2}, found {1} # 0: type, 1: symbol -compiler.err.invalid.containedby.annotation.elem.nondefault=\ +compiler.err.invalid.repeatable.annotation.elem.nondefault=\ containing annotation {0} does not have a default value for element {1} # 0: symbol, 1: type, 2: symbol, 3: type -compiler.err.invalid.containedby.annotation.retention=\ +compiler.err.invalid.repeatable.annotation.retention=\ containing annotation {0} has shorter retention ({1}) than the contained annotation {2} with retention {3} # 0: symbol, 1: symbol -compiler.err.invalid.containedby.annotation.not.documented=\ +compiler.err.invalid.repeatable.annotation.not.documented=\ containing annotation type, {0}, is not @Documented while repeated annotation type, {1}, is # 0: symbol, 1: symbol -compiler.err.invalid.containedby.annotation.not.inherited=\ +compiler.err.invalid.repeatable.annotation.not.inherited=\ containing annotation type, {0}, is not @Inherited while repeated annotation type, {1}, is # 0: symbol, 1: symbol -compiler.err.invalid.containedby.annotation.incompatible.target=\ +compiler.err.invalid.repeatable.annotation.incompatible.target=\ target of container annotation {0} is not a subset of target of repeated annotation {1} # 0: symbol -compiler.err.invalid.containedby.annotation.repeated.and.container.present=\ +compiler.err.invalid.repeatable.annotation.repeated.and.container.present=\ container {0} must not be present at the same time as the element it contains # 0: name @@ -955,6 +948,11 @@ compiler.err.types.incompatible.abstract.default=\ compiler.err.default.overrides.object.member=\ default method {0} in {1} {2} overrides a member of java.lang.Object +# 0: type +compiler.err.illegal.static.intf.meth.call=\ + illegal static interface method call\n\ + the receiver expression should be replaced with the type qualifier ''{0}'' + # 0: type, 1: message segment compiler.err.illegal.default.super.call=\ bad type qualifier {0} in default super call\n\ @@ -1668,6 +1666,9 @@ compiler.misc.bad.const.pool.tag.at=\ compiler.misc.bad.signature=\ bad signature: {0} +compiler.misc.bad.type.annotation.value=\ + bad type annotation target type value: {0} + compiler.misc.class.file.wrong.class=\ class file contains wrong class: {0} @@ -2139,6 +2140,10 @@ compiler.warn.assert.as.identifier=\ as of release 1.4, ''assert'' is a keyword, and may not be used as an identifier\n\ (use -source 1.4 or higher to use ''assert'' as a keyword) +compiler.warn.underscore.as.identifier=\ + ''_'' used as an identifier\n\ + (use of ''_'' as an identifier might not be supported in future releases) + compiler.err.enum.as.identifier=\ as of release 5, ''enum'' is a keyword, and may not be used as an identifier\n\ (use -source 1.4 or lower to use ''enum'' as an identifier) @@ -2147,6 +2152,23 @@ compiler.err.assert.as.identifier=\ as of release 1.4, ''assert'' is a keyword, and may not be used as an identifier\n\ (use -source 1.3 or lower to use ''assert'' as an identifier) +# TODO 308: make a better error message +compiler.err.this.as.identifier=\ + as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter + +# TODO 308: make a better error message +compiler.err.cant.annotate.static.class=\ + enclosing static nested class cannot be annotated +# TODO 308: make a better error message +compiler.err.cant.annotate.nested.type=\ + nested type cannot be annotated + +compiler.err.incorrect.receiver.type=\ + the receiver type does not match the enclosing class type + +compiler.err.no.annotations.on.dot.class=\ + no annotations are allowed in the type of a class literal + # 0: string compiler.err.generics.not.supported.in.source=\ generics are not supported in -source {0}\n\ @@ -2162,9 +2184,10 @@ compiler.err.annotations.not.supported.in.source=\ annotations are not supported in -source {0}\n\ (use -source 5 or higher to enable annotations) -#308 compiler.err.type.annotations.not.supported.in.source=\ -#308 type annotations are not supported in -source {0}\n\ -#308 (use -source 7 or higher to enable type annotations) +# 0: string +compiler.err.type.annotations.not.supported.in.source=\ + type annotations are not supported in -source {0}\n\ +(use -source 8 or higher to enable type annotations) # 0: string compiler.err.foreach.not.supported.in.source=\ @@ -2216,6 +2239,11 @@ compiler.err.intersection.types.in.cast.not.supported.in.source=\ intersection types in cast are not supported in -source {0}\n\ (use -source 8 or higher to enable default methods) +# 0: string +compiler.err.static.intf.methods.not.supported.in.source=\ + static interface methods are not supported in -source {0}\n\ + (use -source 8 or higher to enable static interface methods) + ######################################## # Diagnostics for verbose resolution # used by Resolve (debug only) diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index 890ae3f9597..6f1096aeab2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -1340,6 +1340,10 @@ compiler.err.enum.as.identifier=\u30EA\u30EA\u30FC\u30B95\u304B\u3089''enum''\u3 compiler.err.assert.as.identifier=\u30EA\u30EA\u30FC\u30B91.4\u304B\u3089''assert''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u3001\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\n(''assert''\u3092\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u306B\u306F\u3001-source 1.3\u4EE5\u524D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044) +# TODO 308: make a better error message +# compiler.err.this.as.identifier=\ +# as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter + # 0: string compiler.err.generics.not.supported.in.source=\u7DCF\u79F0\u578B\u306F-source {0}\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\n(\u7DCF\u79F0\u578B\u3092\u4F7F\u7528\u53EF\u80FD\u306B\u3059\u308B\u306B\u306F\u3001-source 5\u4EE5\u964D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044) @@ -1351,7 +1355,7 @@ compiler.err.annotations.not.supported.in.source=\u6CE8\u91C8\u306F-source {0}\u #308 compiler.err.type.annotations.not.supported.in.source=\ #308 type annotations are not supported in -source {0}\n\ -#308 (use -source 7 or higher to enable type annotations) +#308 (use -source 8 or higher to enable type annotations) # 0: string compiler.err.foreach.not.supported.in.source=for-each\u30EB\u30FC\u30D7\u306F-source {0}\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\n(for-each\u30EB\u30FC\u30D7\u3092\u4F7F\u7528\u53EF\u80FD\u306B\u3059\u308B\u306B\u306F\u3001-source 5\u4EE5\u964D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044) diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index 9ede9a363ba..005bc3b3e69 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -1340,6 +1340,10 @@ compiler.err.enum.as.identifier=\u4ECE\u53D1\u884C\u7248 5 \u5F00\u59CB, ''enum' compiler.err.assert.as.identifier=\u4ECE\u53D1\u884C\u7248 1.4 \u5F00\u59CB, ''assert'' \u662F\u4E00\u4E2A\u5173\u952E\u5B57, \u4F46\u4E0D\u80FD\u7528\u4F5C\u6807\u8BC6\u7B26\n(\u8BF7\u4F7F\u7528 -source 1.3 \u6216\u66F4\u4F4E\u7248\u672C\u4EE5\u5C06 ''assert'' \u7528\u4F5C\u6807\u8BC6\u7B26) +# TODO 308: make a better error message +# compiler.err.this.as.identifier=\ +# as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter + # 0: string compiler.err.generics.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\u6301\u6CDB\u578B\n(\u8BF7\u4F7F\u7528 -source 5 \u6216\u66F4\u9AD8\u7248\u672C\u4EE5\u542F\u7528\u6CDB\u578B) @@ -1351,7 +1355,7 @@ compiler.err.annotations.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\ #308 compiler.err.type.annotations.not.supported.in.source=\ #308 type annotations are not supported in -source {0}\n\ -#308 (use -source 7 or higher to enable type annotations) +#308 (use -source 8 or higher to enable type annotations) # 0: string compiler.err.foreach.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\u6301 for-each \u5FAA\u73AF\n(\u8BF7\u4F7F\u7528 -source 5 \u6216\u66F4\u9AD8\u7248\u672C\u4EE5\u542F\u7528 for-each \u5FAA\u73AF) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java index e49cabe0838..c2ca23caf4b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -119,7 +119,7 @@ public abstract class DCTree implements DocTree { } - public static abstract class DCBlockTag extends DCTree implements InlineTagTree { + public static abstract class DCBlockTag extends DCTree implements BlockTagTree { public String getTagName() { return getKind().tagName; } @@ -169,7 +169,7 @@ public abstract class DCTree implements DocTree { } } - public static class DCAuthor extends DCInlineTag implements AuthorTree { + public static class DCAuthor extends DCBlockTag implements AuthorTree { public final List name; DCAuthor(List name) { @@ -640,7 +640,7 @@ public abstract class DCTree implements DocTree { } } - public static class DCSince extends DCInlineTag implements SinceTree { + public static class DCSince extends DCBlockTag implements SinceTree { public final List body; DCSince(List body) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index 269890eeb2b..97a31131440 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -250,11 +250,11 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { */ TYPEAPPLY, - /** Union types, of type TypeUnion + /** Union types, of type TypeUnion. */ TYPEUNION, - /** Intersection types, of type TypeIntersection + /** Intersection types, of type TypeIntersection. */ TYPEINTERSECTION, @@ -274,10 +274,16 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { */ ANNOTATION, + /** metadata: Type annotation. + */ + TYPE_ANNOTATION, + /** metadata: Modifiers */ MODIFIERS, + /** An annotated type tree. + */ ANNOTATED_TYPE, /** Error trees, of type Erroneous. @@ -606,6 +612,42 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } } + /** + * Common supertype for all poly expression trees (lambda, method references, + * conditionals, method and constructor calls) + */ + public static abstract class JCPolyExpression extends JCExpression { + + /** + * A poly expression can only be truly 'poly' in certain contexts + */ + public enum PolyKind { + /** poly expression to be treated as a standalone expression */ + STANDALONE, + /** true poly expression */ + POLY; + } + + /** is this poly expression a 'true' poly expression? */ + public PolyKind polyKind; + } + + /** + * Common supertype for all functional expression trees (lambda and method references) + */ + public static abstract class JCFunctionalExpression extends JCPolyExpression { + + public JCFunctionalExpression() { + //a functional expression is always a 'true' poly + polyKind = PolyKind.POLY; + } + + /** target descriptor inferred for this functional expression. */ + public Type descriptorType; + /** list of target types inferred for this functional expression. */ + public List targets; + } + /** * A class definition. */ @@ -689,6 +731,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public JCExpression restype; /** type parameters */ public List typarams; + /** receiver parameter */ + public JCVariableDecl recvparam; /** value parameters */ public List params; /** exceptions thrown by this method */ @@ -703,6 +747,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { Name name, JCExpression restype, List typarams, + JCVariableDecl recvparam, List params, List thrown, JCBlock body, @@ -714,6 +759,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { this.restype = restype; this.typarams = typarams; this.params = params; + this.recvparam = recvparam; + // TODO: do something special if the given type is null? + // receiver != null ? receiver : List.nil()); this.thrown = thrown; this.body = body; this.defaultValue = defaultValue; @@ -732,6 +780,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public List getParameters() { return params; } + public JCVariableDecl getReceiverParameter() { return recvparam; } public List getThrows() { return thrown; } @@ -1147,7 +1196,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** * A ( ) ? ( ) : ( ) conditional expression */ - public static class JCConditional extends JCExpression implements ConditionalExpressionTree { + public static class JCConditional extends JCPolyExpression implements ConditionalExpressionTree { public JCExpression cond; public JCExpression truepart; public JCExpression falsepart; @@ -1373,7 +1422,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** * A method invocation */ - public static class JCMethodInvocation extends JCExpression implements MethodInvocationTree { + public static class JCMethodInvocation extends JCPolyExpression implements MethodInvocationTree { public List typeargs; public JCExpression meth; public List args; @@ -1416,7 +1465,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** * A new(...) operation. */ - public static class JCNewClass extends JCExpression implements NewClassTree { + public static class JCNewClass extends JCPolyExpression implements NewClassTree { public JCExpression encl; public List typeargs; public JCExpression clazz; @@ -1469,6 +1518,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public static class JCNewArray extends JCExpression implements NewArrayTree { public JCExpression elemtype; public List dims; + // type annotations on inner-most component + public List annotations; + // type annotations on dimensions + public List> dimAnnotations; public List elems; protected JCNewArray(JCExpression elemtype, List dims, @@ -1476,6 +1529,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { { this.elemtype = elemtype; this.dims = dims; + this.annotations = List.nil(); + this.dimAnnotations = List.nil(); this.elems = elems; } @Override @@ -1502,18 +1557,29 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** * A lambda expression. */ - public static class JCLambda extends JCExpression implements LambdaExpressionTree { + public static class JCLambda extends JCFunctionalExpression implements LambdaExpressionTree { + + public enum ParameterKind { + IMPLICIT, + EXPLICIT; + } public List params; public JCTree body; - public Type targetType; public boolean canCompleteNormally = true; public List inferredThrownTypes; + public ParameterKind paramKind; public JCLambda(List params, JCTree body) { this.params = params; this.body = body; + if (params.isEmpty() || + params.head.vartype != null) { + paramKind = ParameterKind.EXPLICIT; + } else { + paramKind = ParameterKind.IMPLICIT; + } } @Override public Tag getTag() { @@ -1812,15 +1878,15 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** * Selects a member expression. */ - public static class JCMemberReference extends JCExpression implements MemberReferenceTree { + public static class JCMemberReference extends JCFunctionalExpression implements MemberReferenceTree { public ReferenceMode mode; public ReferenceKind kind; public Name name; public JCExpression expr; public List typeargs; - public Type targetType; public Symbol sym; public Type varargsElement; + public PolyKind refPolyKind; /** * Javac-dependent classification for member references, based @@ -1838,7 +1904,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { /** Inner # new */ IMPLICIT_INNER(ReferenceMode.NEW, false), /** Toplevel # new */ - TOPLEVEL(ReferenceMode.NEW, false); + TOPLEVEL(ReferenceMode.NEW, false), + /** ArrayType # new */ + ARRAY_CTOR(ReferenceMode.NEW, false); final ReferenceMode mode; final boolean unbound; @@ -2103,9 +2171,12 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public Name name; /** bounds */ public List bounds; - protected JCTypeParameter(Name name, List bounds) { + /** type annotations on type parameter */ + public List annotations; + protected JCTypeParameter(Name name, List bounds, List annotations) { this.name = name; this.bounds = bounds; + this.annotations = annotations; } @Override public void accept(Visitor v) { v.visitTypeParameter(this); } @@ -2115,6 +2186,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public List getBounds() { return bounds; } + public List getAnnotations() { + return annotations; + } @Override public R accept(TreeVisitor v, D d) { return v.visitTypeParameter(this, d); @@ -2181,16 +2255,27 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } public static class JCAnnotation extends JCExpression implements AnnotationTree { + // Either Tag.ANNOTATION or Tag.TYPE_ANNOTATION + private Tag tag; + public JCTree annotationType; public List args; - protected JCAnnotation(JCTree annotationType, List args) { + + // Attribute.Compound if tag is ANNOTATION + // Attribute.TypeCompound if tag is TYPE_ANNOTATION + public Attribute.Compound attribute; + + protected JCAnnotation(Tag tag, JCTree annotationType, List args) { + this.tag = tag; this.annotationType = annotationType; this.args = args; } + @Override public void accept(Visitor v) { v.visitAnnotation(this); } - public Kind getKind() { return Kind.ANNOTATION; } + public Kind getKind() { return TreeInfo.tagToKind(getTag()); } + public JCTree getAnnotationType() { return annotationType; } public List getArguments() { return args; @@ -2201,7 +2286,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } @Override public Tag getTag() { - return ANNOTATION; + return tag; } } @@ -2232,6 +2317,35 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } } + public static class JCAnnotatedType extends JCExpression implements com.sun.source.tree.AnnotatedTypeTree { + // type annotations + public List annotations; + public JCExpression underlyingType; + + protected JCAnnotatedType(List annotations, JCExpression underlyingType) { + this.annotations = annotations; + this.underlyingType = underlyingType; + } + @Override + public void accept(Visitor v) { v.visitAnnotatedType(this); } + + public Kind getKind() { return Kind.ANNOTATED_TYPE; } + public List getAnnotations() { + return annotations; + } + public JCExpression getUnderlyingType() { + return underlyingType; + } + @Override + public R accept(TreeVisitor v, D d) { + return v.visitAnnotatedType(this, d); + } + @Override + public Tag getTag() { + return ANNOTATED_TYPE; + } + } + public static class JCErroneous extends JCExpression implements com.sun.source.tree.ErroneousTree { public List errs; @@ -2298,6 +2412,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { Name name, JCExpression restype, List typarams, + JCVariableDecl recvparam, List params, List thrown, JCBlock body, @@ -2423,6 +2538,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public void visitTypeBoundKind(TypeBoundKind that) { visitTree(that); } public void visitAnnotation(JCAnnotation that) { visitTree(that); } public void visitModifiers(JCModifiers that) { visitTree(that); } + public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); } public void visitErroneous(JCErroneous that) { visitTree(that); } public void visitLetExpr(LetExpr that) { visitTree(that); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java index 9bf69210fcf..3e6c149fbbc 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -29,7 +29,6 @@ import java.io.*; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.tools.javac.code.*; -import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.List; @@ -261,6 +260,15 @@ public class Pretty extends JCTree.Visitor { } } + public void printTypeAnnotations(List trees) throws IOException { + if (trees.nonEmpty()) + print(" "); + for (List l = trees; l.nonEmpty(); l = l.tail) { + printExpr(l.head); + print(" "); + } + } + /** Print documentation comment, if it exists * @param tree The tree for which a documentation comment should be printed. */ @@ -491,6 +499,12 @@ public class Pretty extends JCTree.Visitor { print(" " + tree.name); } print("("); + if (tree.recvparam!=null) { + printExpr(tree.recvparam); + if (tree.params.size() > 0) { + print(", "); + } + } printExprs(tree.params); print(")"); if (tree.thrown.nonEmpty()) { @@ -543,7 +557,15 @@ public class Pretty extends JCTree.Visitor { } else { printExpr(tree.mods); if ((tree.mods.flags & VARARGS) != 0) { - printExpr(((JCArrayTypeTree) tree.vartype).elemtype); + JCTree vartype = tree.vartype; + List tas = null; + if (vartype instanceof JCAnnotatedType) { + tas = ((JCAnnotatedType)vartype).annotations; + vartype = ((JCAnnotatedType)vartype).underlyingType; + } + printExpr(((JCArrayTypeTree) vartype).elemtype); + if (tas != null) + printTypeAnnotations(tas); print("... " + tree.name); } else { printExpr(tree.vartype); @@ -919,16 +941,29 @@ public class Pretty extends JCTree.Visitor { try { if (tree.elemtype != null) { print("new "); + printTypeAnnotations(tree.annotations); JCTree elem = tree.elemtype; - if (elem.hasTag(TYPEARRAY)) - printBaseElementType((JCArrayTypeTree) elem); - else - printExpr(elem); + printBaseElementType(elem); + boolean isElemAnnoType = elem instanceof JCAnnotatedType; + int i = 0; + List> da = tree.dimAnnotations; for (List l = tree.dims; l.nonEmpty(); l = l.tail) { + if (da.size() > i) { + printTypeAnnotations(da.get(i)); + } print("["); + i++; printExpr(l.head); print("]"); } + if (tree.elems != null) { + if (isElemAnnoType) { + printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations); + } + print("[]"); + } + if (isElemAnnoType) + elem = ((JCAnnotatedType)elem).underlyingType; if (elem instanceof JCArrayTypeTree) printBrackets((JCArrayTypeTree) elem); } @@ -946,7 +981,7 @@ public class Pretty extends JCTree.Visitor { public void visitLambda(JCLambda tree) { try { print("("); - if (TreeInfo.isExplicitLambda(tree)) { + if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT) { printExprs(tree.params); } else { String sep = ""; @@ -1225,6 +1260,12 @@ public class Pretty extends JCTree.Visitor { JCTree elem; while (true) { elem = tree.elemtype; + if (elem.hasTag(ANNOTATED_TYPE)) { + JCAnnotatedType atype = (JCAnnotatedType) elem; + elem = atype.underlyingType; + if (!elem.hasTag(TYPEARRAY)) break; + printTypeAnnotations(atype.annotations); + } print("[]"); if (!elem.hasTag(TYPEARRAY)) break; tree = (JCArrayTypeTree) elem; @@ -1327,6 +1368,32 @@ public class Pretty extends JCTree.Visitor { } } + public void visitAnnotatedType(JCAnnotatedType tree) { + try { + if (tree.underlyingType.getKind() == JCTree.Kind.MEMBER_SELECT) { + JCFieldAccess access = (JCFieldAccess) tree.underlyingType; + printExpr(access.selected, TreeInfo.postfixPrec); + print("."); + printTypeAnnotations(tree.annotations); + print(access.name); + } else if (tree.underlyingType.getKind() == JCTree.Kind.ARRAY_TYPE) { + JCArrayTypeTree array = (JCArrayTypeTree) tree.underlyingType; + printBaseElementType(tree); + printTypeAnnotations(tree.annotations); + print("[]"); + JCExpression elem = array.elemtype; + if (elem.hasTag(TYPEARRAY)) { + printBrackets((JCArrayTypeTree) elem); + } + } else { + printTypeAnnotations(tree.annotations); + printExpr(tree.underlyingType); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void visitTree(JCTree tree) { try { print("(UNKNOWN: " + tree + ")"); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java index c2e2ef92290..49f988d8b6d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -71,11 +71,26 @@ public class TreeCopier

implements TreeVisitor { return lb.toList(); } + public JCTree visitAnnotatedType(AnnotatedTypeTree node, P p) { + JCAnnotatedType t = (JCAnnotatedType) node; + List annotations = copy(t.annotations, p); + JCExpression underlyingType = copy(t.underlyingType, p); + return M.at(t.pos).AnnotatedType(annotations, underlyingType); + } + public JCTree visitAnnotation(AnnotationTree node, P p) { JCAnnotation t = (JCAnnotation) node; JCTree annotationType = copy(t.annotationType, p); List args = copy(t.args, p); - return M.at(t.pos).Annotation(annotationType, args); + if (t.getKind() == Tree.Kind.TYPE_ANNOTATION) { + JCAnnotation newTA = M.at(t.pos).TypeAnnotation(annotationType, args); + newTA.attribute = t.attribute; + return newTA; + } else { + JCAnnotation newT = M.at(t.pos).Annotation(annotationType, args); + newT.attribute = t.attribute; + return newT; + } } public JCTree visitAssert(AssertTree node, P p) { @@ -233,10 +248,11 @@ public class TreeCopier

implements TreeVisitor { JCExpression restype = copy(t.restype, p); List typarams = copy(t.typarams, p); List params = copy(t.params, p); + JCVariableDecl recvparam = copy(t.recvparam, p); List thrown = copy(t.thrown, p); JCBlock body = copy(t.body, p); JCExpression defaultValue = copy(t.defaultValue, p); - return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, params, thrown, body, defaultValue); + return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, recvparam, params, thrown, body, defaultValue); } public JCTree visitMethodInvocation(MethodInvocationTree node, P p) { @@ -384,8 +400,9 @@ public class TreeCopier

implements TreeVisitor { public JCTree visitTypeParameter(TypeParameterTree node, P p) { JCTypeParameter t = (JCTypeParameter) node; + List annos = copy(t.annotations, p); List bounds = copy(t.bounds, p); - return M.at(t.pos).TypeParameter(t.name, bounds); + return M.at(t.pos).TypeParameter(t.name, bounds, annos); } public JCTree visitInstanceOf(InstanceOfTree node, P p) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java index 3daff1d5fee..36e3a100729 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -32,6 +32,7 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import static com.sun.tools.javac.code.Flags.*; @@ -264,9 +265,38 @@ public class TreeInfo { } } - public static boolean isExplicitLambda(JCLambda lambda) { - return lambda.params.isEmpty() || - lambda.params.head.vartype != null; + /** set 'polyKind' on given tree */ + public static void setPolyKind(JCTree tree, PolyKind pkind) { + switch (tree.getTag()) { + case APPLY: + ((JCMethodInvocation)tree).polyKind = pkind; + break; + case NEWCLASS: + ((JCNewClass)tree).polyKind = pkind; + break; + case REFERENCE: + ((JCMemberReference)tree).refPolyKind = pkind; + break; + default: + throw new AssertionError("Unexpected tree: " + tree); + } + } + + /** set 'varargsElement' on given tree */ + public static void setVarargsElement(JCTree tree, Type varargsElement) { + switch (tree.getTag()) { + case APPLY: + ((JCMethodInvocation)tree).varargsElement = varargsElement; + break; + case NEWCLASS: + ((JCNewClass)tree).varargsElement = varargsElement; + break; + case REFERENCE: + ((JCMemberReference)tree).varargsElement = varargsElement; + break; + default: + throw new AssertionError("Unexpected tree: " + tree); + } } /** Return true if the tree corresponds to an expression statement */ @@ -423,6 +453,19 @@ public class TreeInfo { case POSTINC: case POSTDEC: return getStartPos(((JCUnary) tree).arg); + case ANNOTATED_TYPE: { + JCAnnotatedType node = (JCAnnotatedType) tree; + if (node.annotations.nonEmpty()) { + if (node.underlyingType.hasTag(TYPEARRAY) || + node.underlyingType.hasTag(SELECT)) { + return getStartPos(node.underlyingType); + } else { + return getStartPos(node.annotations.head); + } + } else { + return getStartPos(node.underlyingType); + } + } case NEWCLASS: { JCNewClass node = (JCNewClass)tree; if (node.encl != null) @@ -530,6 +573,8 @@ public class TreeInfo { return getEndPos(((JCUnary) tree).arg, endPosTable); case WHILELOOP: return getEndPos(((JCWhileLoop) tree).body, endPosTable); + case ANNOTATED_TYPE: + return getEndPos(((JCAnnotatedType) tree).underlyingType, endPosTable); case ERRONEOUS: { JCErroneous node = (JCErroneous)tree; if (node.errs != null && node.errs.nonEmpty()) @@ -769,6 +814,8 @@ public class TreeInfo { return ((JCFieldAccess) tree).sym; case TYPEAPPLY: return symbol(((JCTypeApply) tree).clazz); + case ANNOTATED_TYPE: + return symbol(((JCAnnotatedType) tree).underlyingType); default: return null; } @@ -1006,17 +1053,24 @@ public class TreeInfo { case NULLCHK: return Tree.Kind.OTHER; + case ANNOTATION: + return Tree.Kind.ANNOTATION; + case TYPE_ANNOTATION: + return Tree.Kind.TYPE_ANNOTATION; + default: return null; } } /** - * Returns the underlying type of the tree if it is annotated type, - * or the tree itself otherwise + * Returns the underlying type of the tree if it is an annotated type, + * or the tree itself otherwise. */ public static JCExpression typeIn(JCExpression tree) { switch (tree.getTag()) { + case ANNOTATED_TYPE: + return ((JCAnnotatedType)tree).underlyingType; case IDENT: /* simple names */ case TYPEIDENT: /* primitive name */ case SELECT: /* qualified name */ @@ -1024,20 +1078,55 @@ public class TreeInfo { case WILDCARD: /* wild cards */ case TYPEPARAMETER: /* type parameters */ case TYPEAPPLY: /* parameterized types */ + case ERRONEOUS: /* error tree TODO: needed for BadCast JSR308 test case. Better way? */ return tree; default: throw new AssertionError("Unexpected type tree: " + tree); } } + /* Return the inner-most type of a type tree. + * For an array that contains an annotated type, return that annotated type. + * TODO: currently only used by Pretty. Describe behavior better. + */ public static JCTree innermostType(JCTree type) { - switch (type.getTag()) { - case TYPEARRAY: - return innermostType(((JCArrayTypeTree)type).elemtype); - case WILDCARD: - return innermostType(((JCWildcard)type).inner); - default: - return type; + JCTree lastAnnotatedType = null; + JCTree cur = type; + loop: while (true) { + switch (cur.getTag()) { + case TYPEARRAY: + lastAnnotatedType = null; + cur = ((JCArrayTypeTree)cur).elemtype; + break; + case WILDCARD: + lastAnnotatedType = null; + cur = ((JCWildcard)cur).inner; + break; + case ANNOTATED_TYPE: + lastAnnotatedType = cur; + cur = ((JCAnnotatedType)cur).underlyingType; + break; + default: + break loop; + } + } + if (lastAnnotatedType!=null) { + return lastAnnotatedType; + } else { + return cur; } } + + private static class TypeAnnotationFinder extends TreeScanner { + public boolean foundTypeAnno = false; + public void visitAnnotation(JCAnnotation tree) { + foundTypeAnno = foundTypeAnno || tree.hasTag(TYPE_ANNOTATION); + } + } + + public static boolean containsTypeAnnotation(JCTree e) { + TypeAnnotationFinder finder = new TypeAnnotationFinder(); + finder.scan(e); + return finder.foundTypeAnno; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 27a2d74feda..cc6405e22d9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -169,10 +169,26 @@ public class TreeMaker implements JCTree.Factory { List thrown, JCBlock body, JCExpression defaultValue) { + return MethodDef( + mods, name, restype, typarams, null, params, + thrown, body, defaultValue); + } + + public JCMethodDecl MethodDef(JCModifiers mods, + Name name, + JCExpression restype, + List typarams, + JCVariableDecl recvparam, + List params, + List thrown, + JCBlock body, + JCExpression defaultValue) + { JCMethodDecl tree = new JCMethodDecl(mods, name, restype, typarams, + recvparam, params, thrown, body, @@ -463,7 +479,11 @@ public class TreeMaker implements JCTree.Factory { } public JCTypeParameter TypeParameter(Name name, List bounds) { - JCTypeParameter tree = new JCTypeParameter(name, bounds); + return TypeParameter(name, bounds, List.nil()); + } + + public JCTypeParameter TypeParameter(Name name, List bounds, List annos) { + JCTypeParameter tree = new JCTypeParameter(name, bounds, annos); tree.pos = pos; return tree; } @@ -481,7 +501,13 @@ public class TreeMaker implements JCTree.Factory { } public JCAnnotation Annotation(JCTree annotationType, List args) { - JCAnnotation tree = new JCAnnotation(annotationType, args); + JCAnnotation tree = new JCAnnotation(Tag.ANNOTATION, annotationType, args); + tree.pos = pos; + return tree; + } + + public JCAnnotation TypeAnnotation(JCTree annotationType, List args) { + JCAnnotation tree = new JCAnnotation(Tag.TYPE_ANNOTATION, annotationType, args); tree.pos = pos; return tree; } @@ -497,6 +523,12 @@ public class TreeMaker implements JCTree.Factory { return Modifiers(flags, List.nil()); } + public JCAnnotatedType AnnotatedType(List annotations, JCExpression underlyingType) { + JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType); + tree.pos = pos; + return tree; + } + public JCErroneous Erroneous() { return Erroneous(List.nil()); } @@ -755,7 +787,11 @@ public class TreeMaker implements JCTree.Factory { result = Erroneous(); } public void visitCompound(Attribute.Compound compound) { - result = visitCompoundInternal(compound); + if (compound instanceof Attribute.TypeCompound) { + result = visitTypeCompoundInternal((Attribute.TypeCompound) compound); + } else { + result = visitCompoundInternal(compound); + } } public JCAnnotation visitCompoundInternal(Attribute.Compound compound) { ListBuffer args = new ListBuffer(); @@ -766,6 +802,15 @@ public class TreeMaker implements JCTree.Factory { } return Annotation(Type(compound.type), args.toList()); } + public JCAnnotation visitTypeCompoundInternal(Attribute.TypeCompound compound) { + ListBuffer args = new ListBuffer(); + for (List> values = compound.values; values.nonEmpty(); values=values.tail) { + Pair pair = values.head; + JCExpression valueTree = translate(pair.snd); + args.append(Assign(Ident(pair.fst), valueTree).setType(valueTree.type)); + } + return TypeAnnotation(Type(compound.type), args.toList()); + } public void visitArray(Attribute.Array array) { ListBuffer elems = new ListBuffer(); for (int i = 0; i < array.values.length; i++) @@ -779,7 +824,11 @@ public class TreeMaker implements JCTree.Factory { JCAnnotation translate(Attribute.Compound a) { return visitCompoundInternal(a); } + JCAnnotation translate(Attribute.TypeCompound a) { + return visitTypeCompoundInternal(a); + } } + AnnotationBuilder annotationBuilder = new AnnotationBuilder(); /** Create an annotation tree from an attribute. @@ -788,6 +837,10 @@ public class TreeMaker implements JCTree.Factory { return annotationBuilder.translate((Attribute.Compound)a); } + public JCAnnotation TypeAnnotation(Attribute a) { + return annotationBuilder.translate((Attribute.TypeCompound) a); + } + /** Create a method definition from a method symbol and a method body. */ public JCMethodDecl MethodDef(MethodSymbol m, JCBlock body) { @@ -804,6 +857,7 @@ public class TreeMaker implements JCTree.Factory { m.name, Type(mtype.getReturnType()), TypeParams(mtype.getTypeArguments()), + null, // receiver type Params(mtype.getParameterTypes(), m), Types(mtype.getThrownTypes()), body, @@ -822,7 +876,6 @@ public class TreeMaker implements JCTree.Factory { */ public List TypeParams(List typarams) { ListBuffer tparams = new ListBuffer(); - int i = 0; for (List l = typarams; l.nonEmpty(); l = l.tail) tparams.append(TypeParam(l.head.tsym.name, (TypeVar)l.head)); return tparams.toList(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java index eff0fe2c617..57724d34292 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -84,6 +84,7 @@ public class TreeScanner extends Visitor { scan(tree.mods); scan(tree.restype); scan(tree.typarams); + scan(tree.recvparam); scan(tree.params); scan(tree.thrown); scan(tree.defaultValue); @@ -200,15 +201,18 @@ public class TreeScanner extends Visitor { public void visitNewClass(JCNewClass tree) { scan(tree.encl); - scan(tree.clazz); scan(tree.typeargs); + scan(tree.clazz); scan(tree.args); scan(tree.def); } public void visitNewArray(JCNewArray tree) { + scan(tree.annotations); scan(tree.elemtype); scan(tree.dims); + for (List annos : tree.dimAnnotations) + scan(annos); scan(tree.elems); } @@ -291,6 +295,7 @@ public class TreeScanner extends Visitor { } public void visitTypeParameter(JCTypeParameter tree) { + scan(tree.annotations); scan(tree.bounds); } @@ -314,6 +319,11 @@ public class TreeScanner extends Visitor { scan(tree.args); } + public void visitAnnotatedType(JCAnnotatedType tree) { + scan(tree.annotations); + scan(tree.underlyingType); + } + public void visitErroneous(JCErroneous tree) { } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java index daf456fa90d..42e97deee11 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -139,6 +139,7 @@ public class TreeTranslator extends JCTree.Visitor { tree.mods = translate(tree.mods); tree.restype = translate(tree.restype); tree.typarams = translateTypeParams(tree.typarams); + tree.recvparam = translate(tree.recvparam); tree.params = translateVarDefs(tree.params); tree.thrown = translate(tree.thrown); tree.body = translate(tree.body); @@ -289,6 +290,11 @@ public class TreeTranslator extends JCTree.Visitor { } public void visitNewArray(JCNewArray tree) { + tree.annotations = translate(tree.annotations); + List> dimAnnos = List.nil(); + for (List origDimAnnos : tree.dimAnnotations) + dimAnnos = dimAnnos.append(translate(origDimAnnos)); + tree.dimAnnotations = dimAnnos; tree.elemtype = translate(tree.elemtype); tree.dims = translate(tree.dims); tree.elems = translate(tree.elems); @@ -385,6 +391,7 @@ public class TreeTranslator extends JCTree.Visitor { } public void visitTypeParameter(JCTypeParameter tree) { + tree.annotations = translate(tree.annotations); tree.bounds = translate(tree.bounds); result = tree; } @@ -422,6 +429,12 @@ public class TreeTranslator extends JCTree.Visitor { result = tree; } + public void visitAnnotatedType(JCAnnotatedType tree) { + tree.annotations = translate(tree.annotations); + tree.underlyingType = translate(tree.underlyingType); + result = tree; + } + public void visitTree(JCTree tree) { throw new AssertionError(tree); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java index 17ce2319dc1..be531e0ef03 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -388,7 +388,7 @@ public class JCDiagnostic implements Diagnostic { this.source = source; this.position = pos; this.key = key; - this.args = args; + this.args = args; int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition()); if (n == Position.NOPOS || source == null) diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java index 70267f7097c..4ed16c1eb6d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -217,7 +217,7 @@ public class Log extends AbstractLog { private JavacMessages messages; /** -+ * Handler for initial dispatch of diagnostics. + * Handler for initial dispatch of diagnostics. */ private DiagnosticHandler diagnosticHandler; @@ -385,14 +385,17 @@ public class Log extends AbstractLog { noticeWriter = warnWriter = errWriter = pw; } - public void setWriters(Log other) { + /** + * Propagate the previous log's information. + */ + public void initRound(Log other) { this.noticeWriter = other.noticeWriter; this.warnWriter = other.warnWriter; this.errWriter = other.errWriter; - } - - public void setSourceMap(Log other) { this.sourceMap = other.sourceMap; + this.recorded = other.recorded; + this.nerrors = other.nerrors; + this.nwarnings = other.nwarnings; } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java index 46867d5fa75..7c5849d2758 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java @@ -288,7 +288,7 @@ public class RichDiagnosticFormatter extends public String simplify(Symbol s) { String name = s.getQualifiedName().toString(); - if (!s.type.isCompound()) { + if (!s.type.isCompound() && !s.type.isPrimitive()) { List conflicts = nameClashes.get(s.getSimpleName()); if (conflicts == null || (conflicts.size() == 1 && diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java index e589bfa8678..6adcb43f90b 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,4 +104,8 @@ abstract class AbstractTypeImpl implements com.sun.javadoc.Type { public AnnotationTypeDoc asAnnotationTypeDoc() { return null; } + + public AnnotatedType asAnnotatedType() { + return null; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java new file mode 100644 index 00000000000..a49dc8a3134 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.javadoc; + +import com.sun.javadoc.*; +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Attribute.TypeCompound; +import com.sun.tools.javac.util.List; + +/** + * Implementation of AnnotatedType, which + * represents an annotated type. + * + * @author Mahmood Ali + * @since 1.8 + */ +public class AnnotatedTypeImpl + extends AbstractTypeImpl implements AnnotatedType { + + AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type.AnnotatedType type) { + super(env, type); + } + + /** + * Get the annotations of this program element. + * Return an empty array if there are none. + */ + @Override + public AnnotationDesc[] annotations() { + List tas = ((com.sun.tools.javac.code.Type.AnnotatedType)type).typeAnnotations; + if (tas == null || + tas.isEmpty()) { + return new AnnotationDesc[0]; + } + AnnotationDesc res[] = new AnnotationDesc[tas.length()]; + int i = 0; + for (Attribute.Compound a : tas) { + res[i++] = new AnnotationDescImpl(env, a); + } + return res; + } + + @Override + public com.sun.javadoc.Type underlyingType() { + return TypeMaker.getType(env, ((com.sun.tools.javac.code.Type.AnnotatedType)type).underlyingType, true, false); + } + + @Override + public AnnotatedType asAnnotatedType() { + return this; + } + + @Override + public String toString() { + return typeName(); + } + + @Override + public String typeName() { + return this.underlyingType().typeName(); + } + + @Override + public String qualifiedTypeName() { + return this.underlyingType().qualifiedTypeName(); + } + + @Override + public String simpleTypeName() { + return this.underlyingType().simpleTypeName(); + } + + @Override + public String dimension() { + return this.underlyingType().dimension(); + } + + @Override + public boolean isPrimitive() { + return this.underlyingType().isPrimitive(); + } + + @Override + public ClassDoc asClassDoc() { + return this.underlyingType().asClassDoc(); + } + + @Override + public TypeVariable asTypeVariable() { + return this.underlyingType().asTypeVariable(); + } + + @Override + public WildcardType asWildcardType() { + return this.underlyingType().asWildcardType(); + } + + @Override + public ParameterizedType asParameterizedType() { + return this.underlyingType().asParameterizedType(); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java index ffcc5e7853f..3d1ac353cc0 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1185,6 +1185,13 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc { return null; } + /** + * Returns null, as this is not an annotated type. + */ + public AnnotatedType asAnnotatedType() { + return null; + } + /** * Return false, as this is not a primitive type. */ diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java index ba08ae47eaa..0cac65c422a 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -31,8 +31,10 @@ import java.util.*; import javax.tools.JavaFileManager; import com.sun.javadoc.*; +import com.sun.source.util.JavacTask; import com.sun.source.util.TreePath; -import com.sun.tools.javac.api.JavacTrees; +import com.sun.tools.doclint.DocLint; +import com.sun.tools.javac.api.BasicJavacTask; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.ClassType; @@ -105,6 +107,7 @@ public class DocEnv { Types types; JavaFileManager fileManager; Context context; + DocLint doclint; WeakHashMap treePaths = new WeakHashMap(); @@ -400,6 +403,9 @@ public class DocEnv { public void warning(DocImpl doc, String key, String a1) { if (silent) return; + // suppress messages that have (probably) been covered by doclint + if (doclint != null && doc != null && key.startsWith("tag")) + return; messager.warning(doc==null ? null : doc.position(), key, a1); } @@ -732,9 +738,15 @@ public class DocEnv { return p; } - TreePath getTreePath(JCCompilationUnit toplevel, JCTree tree) { - // don't bother to cache paths for classes and members - return new TreePath(getTreePath(toplevel), tree); + TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) { + TreePath p = treePaths.get(tree); + if (p == null) + treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); + return p; + } + + TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) { + return new TreePath(getTreePath(toplevel, cdecl), tree); } /** @@ -781,4 +793,25 @@ public class DocEnv { result |= Modifier.VOLATILE; return result; } + + void initDoclint(Collection opts) { + ArrayList doclintOpts = new ArrayList(); + + for (String opt: opts) { + doclintOpts.add(opt == null ? DocLint.XMSGS_OPTION : DocLint.XMSGS_CUSTOM_PREFIX + opt); + } + + if (doclintOpts.size() == 1 + && doclintOpts.get(0).equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) { + return; + } + + JavacTask t = BasicJavacTask.instance(context); + doclint = new DocLint(); + doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false); + } + + boolean showTagMessages() { + return (doclint == null); + } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java index 12451293c9a..e5b3f6c9980 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,7 +126,13 @@ public abstract class DocImpl implements Doc, Comparable { */ Comment comment() { if (comment == null) { - comment = new Comment(this, documentation()); + String d = documentation(); + if (env.doclint != null + && treePath != null + && d.equals(getCommentText(treePath))) { + env.doclint.scan(treePath); + } + comment = new Comment(this, d); } return comment; } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java index 72a666d27a7..a1a741d10ff 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,14 @@ package com.sun.tools.javadoc; import java.lang.reflect.Modifier; import java.text.CollationKey; +import javax.lang.model.type.TypeKind; + import com.sun.javadoc.*; import com.sun.source.util.TreePath; +import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Attribute.Compound; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.util.List; @@ -195,6 +199,24 @@ public abstract class ExecutableMemberDocImpl return result; } + public AnnotationDesc[] receiverAnnotations() { + // TODO: change how receiver annotations are output! + Type recvtype = sym.type.asMethodType().recvtype; + if (recvtype == null) { + return new AnnotationDesc[0]; + } + if (recvtype.getKind() != TypeKind.ANNOTATED) { + return new AnnotationDesc[0]; + } + List typeAnnos = ((com.sun.tools.javac.code.Type.AnnotatedType)recvtype).typeAnnotations; + AnnotationDesc result[] = new AnnotationDesc[typeAnnos.length()]; + int i = 0; + for (Attribute.Compound a : typeAnnos) { + result[i++] = new AnnotationDescImpl(env, a); + } + return result; + } + /** * Return the formal type parameters of this method or constructor. * Return an empty array if there are none. diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java index 76e93a34367..058d173ebe7 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,7 @@ public class JavadocMemberEnter extends MemberEnter { super.visitMethodDef(tree); MethodSymbol meth = tree.sym; if (meth == null || meth.kind != Kinds.MTH) return; - TreePath treePath = docenv.getTreePath(env.toplevel, tree); + TreePath treePath = docenv.getTreePath(env.toplevel, env.enclClass, tree); if (meth.isConstructor()) docenv.makeConstructorDoc(meth, treePath); else if (isAnnotationTypeElement(meth)) @@ -90,7 +90,7 @@ public class JavadocMemberEnter extends MemberEnter { if (tree.sym != null && tree.sym.kind == Kinds.VAR && !isParameter(tree.sym)) { - docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, tree)); + docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, env.enclClass, tree)); } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java b/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java index 15679a79f46..9f6345f98b0 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -121,12 +121,19 @@ class PrimitiveType implements com.sun.javadoc.Type { } /** - * Return null, as this is not a wildcard type; + * Return null, as this is not a wildcard type. */ public WildcardType asWildcardType() { return null; } + /** + * Return null, as this is not an annotated type. + */ + public AnnotatedType asAnnotatedType() { + return null; + } + /** * Returns a string representation of the type. * diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java index f662dd749db..89a086aa8f8 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,14 @@ package com.sun.tools.javadoc; import java.io.IOException; +import java.util.Collection; import java.util.Locale; + import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import com.sun.javadoc.*; - import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -375,4 +376,12 @@ public class RootDocImpl extends DocImpl implements RootDoc { public JavaFileManager getFileManager() { return env.fileManager; } + + public void initDocLint(Collection opts) { + env.initDoclint(opts); + } + + public boolean showTagMessages() { + return env.showTagMessages(); + } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java index dd0f355fa24..4a24e9406a5 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.tools.javadoc; +import javax.lang.model.type.TypeKind; + import com.sun.javadoc.*; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; @@ -51,12 +53,27 @@ public class TypeMaker { * @param errToClassDoc if true, ERROR type results in a ClassDoc; * false preserves legacy behavior */ + public static com.sun.javadoc.Type getType(DocEnv env, Type t, + boolean errorToClassDoc) { + return getType(env, t, errorToClassDoc, true); + } + @SuppressWarnings("fallthrough") public static com.sun.javadoc.Type getType(DocEnv env, Type t, - boolean errToClassDoc) { + boolean errToClassDoc, boolean considerAnnotations) { if (env.legacyDoclet) { t = env.types.erasure(t); } + if (considerAnnotations + && t.getKind() == TypeKind.ANNOTATED) { + return new AnnotatedTypeImpl(env, (com.sun.tools.javac.code.Type.AnnotatedType) t); + } + + if (t.getKind() == TypeKind.ANNOTATED) { + Type.AnnotatedType at = (Type.AnnotatedType) t; + return new AnnotatedTypeImpl(env, at); + } + switch (t.getTag()) { case CLASS: if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) { @@ -129,6 +146,11 @@ public class TypeMaker { * Class names are qualified if "full" is true. */ static String getTypeString(DocEnv env, Type t, boolean full) { + // TODO: should annotations be included here? + if (t.getKind() == TypeKind.ANNOTATED) { + Type.AnnotatedType at = (Type.AnnotatedType)t; + t = at.underlyingType; + } switch (t.getTag()) { case ARRAY: StringBuilder s = new StringBuilder(); @@ -281,6 +303,13 @@ public class TypeMaker { return null; } + /** + * Return null, as there are no annotations of the type + */ + public AnnotatedType asAnnotatedType() { + return null; + } + /** * Return this type as an AnnotationTypeDoc if it * represents an annotation type. Array dimensions are ignored. diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java index 85f946c6bf9..19a5bb9fab4 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,12 @@ package com.sun.tools.javadoc; +import javax.lang.model.type.TypeKind; + import com.sun.javadoc.*; +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Attribute.TypeCompound; import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; @@ -120,11 +124,30 @@ public class TypeVariableImpl extends AbstractTypeImpl implements TypeVariable { * Get the bounds of a type variable as listed in the "extends" clause. */ private static List getBounds(TypeVar v, DocEnv env) { - Name boundname = v.getUpperBound().tsym.getQualifiedName(); - if (boundname == boundname.table.names.java_lang_Object) { + final Type upperBound = v.getUpperBound(); + Name boundname = upperBound.tsym.getQualifiedName(); + if (boundname == boundname.table.names.java_lang_Object + && upperBound.getKind() != TypeKind.ANNOTATED) { return List.nil(); } else { return env.types.getBounds(v); } } + + /** + * Get the annotations of this program element. + * Return an empty array if there are none. + */ + public AnnotationDesc[] annotations() { + if (type.getKind() != TypeKind.ANNOTATED) { + return new AnnotationDesc[0]; + } + List tas = ((com.sun.tools.javac.code.Type.AnnotatedType) type).typeAnnotations; + AnnotationDesc res[] = new AnnotationDesc[tas.length()]; + int i = 0; + for (Attribute.Compound a : tas) { + res[i++] = new AnnotationDescImpl(env, a); + } + return res; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java index a8aa2786577..5df92804aa1 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -139,12 +139,13 @@ public class JavadocTool implements DocumentationTool { @Override public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) { - PrintWriter err_pw = new PrintWriter(err, true); - PrintWriter out_pw = new PrintWriter(out); + PrintWriter err_pw = new PrintWriter(err == null ? System.err : err, true); + PrintWriter out_pw = new PrintWriter(out == null ? System.out : out); try { String standardDocletName = "com.sun.tools.doclets.standard.Standard"; + ClassLoader cl = getClass().getClassLoader(); return com.sun.tools.javadoc.Main.execute( - "javadoc", err_pw, err_pw, out_pw, standardDocletName, arguments); + "javadoc", err_pw, err_pw, out_pw, standardDocletName, cl, arguments); } finally { err_pw.flush(); out_pw.flush(); diff --git a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java index 37ec6b291e4..6f894e7cb62 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -26,6 +26,7 @@ package com.sun.tools.javap; import com.sun.tools.classfile.Annotation; +import com.sun.tools.classfile.TypeAnnotation; import com.sun.tools.classfile.Annotation.Annotation_element_value; import com.sun.tools.classfile.Annotation.Array_element_value; import com.sun.tools.classfile.Annotation.Class_element_value; @@ -76,6 +77,124 @@ public class AnnotationWriter extends BasicWriter { print(")"); } + public void write(TypeAnnotation annot) { + write(annot, true, false); + } + + public void write(TypeAnnotation annot, boolean showOffsets, boolean resolveIndices) { + write(annot.annotation, resolveIndices); + print(": "); + write(annot.position, showOffsets); + } + + public void write(TypeAnnotation.Position pos, boolean showOffsets) { + print(pos.type); + + switch (pos.type) { + // type cast + case CAST: + // instanceof + case INSTANCEOF: + // new expression + case NEW: + if (showOffsets) { + print(", offset="); + print(pos.offset); + } + break; + // local variable + case LOCAL_VARIABLE: + // resource variable + case RESOURCE_VARIABLE: + if (pos.lvarOffset == null) { + print(", lvarOffset is Null!"); + break; + } + print(", {"); + for (int i = 0; i < pos.lvarOffset.length; ++i) { + if (i != 0) print("; "); + if (showOffsets) { + print("start_pc="); + print(pos.lvarOffset[i]); + } + print(", length="); + print(pos.lvarLength[i]); + print(", index="); + print(pos.lvarIndex[i]); + } + print("}"); + break; + // exception parameter + case EXCEPTION_PARAMETER: + print(", exception_index="); + print(pos.exception_index); + break; + // method receiver + case METHOD_RECEIVER: + // Do nothing + break; + // type parameter + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: + print(", param_index="); + print(pos.parameter_index); + break; + // type parameter bound + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + print(", param_index="); + print(pos.parameter_index); + print(", bound_index="); + print(pos.bound_index); + break; + // class extends or implements clause + case CLASS_EXTENDS: + print(", type_index="); + print(pos.type_index); + break; + // throws + case THROWS: + print(", type_index="); + print(pos.type_index); + break; + // method parameter + case METHOD_FORMAL_PARAMETER: + print(", param_index="); + print(pos.parameter_index); + break; + // method/constructor/reference type argument + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: + if (showOffsets) { + print(", offset="); + print(pos.offset); + } + print(", type_index="); + print(pos.type_index); + break; + // We don't need to worry about these + case METHOD_RETURN: + case FIELD: + break; + // lambda formal parameter + case LAMBDA_FORMAL_PARAMETER: + print(", param_index="); + print(pos.parameter_index); + break; + case UNKNOWN: + throw new AssertionError("AnnotationWriter: UNKNOWN target type should never occur!"); + default: + throw new AssertionError("AnnotationWriter: Unknown target type for position: " + pos); + } + + // Append location data for generics/arrays. + if (!pos.location.isEmpty()) { + print(", location="); + print(pos.location); + } + } + public void write(Annotation.element_value_pair pair) { write(pair, false); } diff --git a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java index 329dccb2f87..d25477b237e 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -49,8 +49,10 @@ import com.sun.tools.classfile.LocalVariableTypeTable_attribute; import com.sun.tools.classfile.MethodParameters_attribute; import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; import com.sun.tools.classfile.Signature_attribute; import com.sun.tools.classfile.SourceDebugExtension_attribute; import com.sun.tools.classfile.SourceFile_attribute; @@ -433,6 +435,30 @@ public class AttributeWriter extends BasicWriter return null; } + public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) { + println("RuntimeVisibleTypeAnnotations:"); + indent(+1); + for (int i = 0; i < attr.annotations.length; i++) { + print(i + ": "); + annotationWriter.write(attr.annotations[i]); + println(); + } + indent(-1); + return null; + } + + public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) { + println("RuntimeInvisibleTypeAnnotations:"); + indent(+1); + for (int i = 0; i < attr.annotations.length; i++) { + print(i + ": "); + annotationWriter.write(attr.annotations[i]); + println(); + } + indent(-1); + return null; + } + public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) { println("RuntimeVisibleParameterAnnotations:"); indent(+1); diff --git a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java index 50ce27dcbdf..657194d19c6 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -64,6 +64,7 @@ public class CodeWriter extends BasicWriter { stackMapWriter = StackMapWriter.instance(context); localVariableTableWriter = LocalVariableTableWriter.instance(context); localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context); + typeAnnotationWriter = TypeAnnotationWriter.instance(context); options = Options.instance(context); } @@ -265,6 +266,11 @@ public class CodeWriter extends BasicWriter { detailWriters.add(tryBlockWriter); } + if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) { + typeAnnotationWriter.reset(attr); + detailWriters.add(typeAnnotationWriter); + } + return detailWriters; } @@ -273,6 +279,7 @@ public class CodeWriter extends BasicWriter { private ConstantWriter constantWriter; private LocalVariableTableWriter localVariableTableWriter; private LocalVariableTypeTableWriter localVariableTypeTableWriter; + private TypeAnnotationWriter typeAnnotationWriter; private SourceWriter sourceWriter; private StackMapWriter stackMapWriter; private TryBlockWriter tryBlockWriter; diff --git a/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java b/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java index 7459d6c0d11..8a828b8f2b3 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -42,10 +42,13 @@ public abstract class InstructionDetailWriter extends BasicWriter { LOCAL_VAR_TYPES("localVariableTypes"), SOURCE("source"), STACKMAPS("stackMaps"), - TRY_BLOCKS("tryBlocks"); + TRY_BLOCKS("tryBlocks"), + TYPE_ANNOS("typeAnnotations"); + Kind(String option) { this.option = option; } + final String option; } diff --git a/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java b/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java new file mode 100644 index 00000000000..e5a3a68f1a3 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2009, 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 com.sun.tools.javap; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.TypeAnnotation; +import com.sun.tools.classfile.TypeAnnotation.Position; +import com.sun.tools.classfile.Instruction; +import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; +import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Annotate instructions with details about type annotations. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class TypeAnnotationWriter extends InstructionDetailWriter { + public enum NoteKind { VISIBLE, INVISIBLE }; + public static class Note { + Note(NoteKind kind, TypeAnnotation anno) { + this.kind = kind; + this.anno = anno; + } + public final NoteKind kind; + public final TypeAnnotation anno; + } + + static TypeAnnotationWriter instance(Context context) { + TypeAnnotationWriter instance = context.get(TypeAnnotationWriter.class); + if (instance == null) + instance = new TypeAnnotationWriter(context); + return instance; + } + + protected TypeAnnotationWriter(Context context) { + super(context); + context.put(TypeAnnotationWriter.class, this); + annotationWriter = AnnotationWriter.instance(context); + classWriter = ClassWriter.instance(context); + } + + public void reset(Code_attribute attr) { + Method m = classWriter.getMethod(); + pcMap = new HashMap>(); + check(NoteKind.VISIBLE, (RuntimeVisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeVisibleTypeAnnotations)); + check(NoteKind.INVISIBLE, (RuntimeInvisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeInvisibleTypeAnnotations)); + } + + private void check(NoteKind kind, RuntimeTypeAnnotations_attribute attr) { + if (attr == null) + return; + + for (TypeAnnotation anno: attr.annotations) { + Position p = anno.position; + Note note = null; + if (p.offset != -1) + addNote(p.offset, note = new Note(kind, anno)); + if (p.lvarOffset != null) { + for (int i = 0; i < p.lvarOffset.length; i++) { + if (note == null) + note = new Note(kind, anno); + addNote(p.lvarOffset[i], note); + } + } + } + } + + private void addNote(int pc, Note note) { + List list = pcMap.get(pc); + if (list == null) + pcMap.put(pc, list = new ArrayList()); + list.add(note); + } + + @Override + void writeDetails(Instruction instr) { + String indent = space(2); // get from Options? + int pc = instr.getPC(); + List notes = pcMap.get(pc); + if (notes != null) { + for (Note n: notes) { + print(indent); + print("@"); + annotationWriter.write(n.anno, false, true); + print(", "); + println(n.kind.toString().toLowerCase()); + } + } + } + + private AnnotationWriter annotationWriter; + private ClassWriter classWriter; + private Map> pcMap; +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java b/langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java new file mode 100644 index 00000000000..9b90950290c --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * The build state class captures the source code and generated artifacts + * from a build. There are usually two build states, the previous one (prev), + * loaded from the javac_state file, and the current one (now). + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class BuildState { + private Map modules = new HashMap(); + private Map packages = new HashMap(); + private Map sources = new HashMap(); + private Map artifacts = new HashMap(); + // Map from package to a set of packages that depend on said package. + private Map> dependents = new HashMap>(); + + public Map modules() { return modules; } + public Map packages() { return packages; } + public Map sources() { return sources; } + public Map artifacts() { return artifacts; } + public Map> dependents() { return dependents; } + + /** + * Lookup a module from a name. Create the module if it does + * not exist yet. + */ + public Module lookupModule(String mod) { + Module m = modules.get(mod); + if (m == null) { + m = new Module(mod, "???"); + modules.put(mod, m); + } + return m; + } + + /** + * Find a module from a given package name. For example: + * The package name "base:java.lang" will fetch the module named "base". + * The package name ":java.net" will fetch the default module. + */ + Module findModuleFromPackageName(String pkg) { + int cp = pkg.indexOf(':'); + assert(cp != -1); + String mod = pkg.substring(0, cp); + return lookupModule(mod); + } + + /** + * Collect all packages, sources and artifacts for all modules + * into the build state. + * + * @param m The set of modules. + */ + public void collectPackagesSourcesAndArtifacts(Map m) { + modules = m; + // Extract all the found packages. + for (Module i : modules.values()) { + for (Map.Entry j : i.packages().entrySet()) { + Package p = packages.get(j.getKey()); + // Check that no two different packages are stored under same name. + assert(p == null || p == j.getValue()); + if (p == null) { + p = j.getValue(); + packages.put(j.getKey(),j.getValue()); + } + for (Map.Entry k : p.sources().entrySet()) { + Source s = sources.get(k.getKey()); + // Check that no two different sources are stored under same name. + assert(s == null || s == k.getValue()); + if (s == null) { + s = k.getValue(); + sources.put(k.getKey(), k.getValue()); + } + } + for (Map.Entry g : p.artifacts().entrySet()) { + File f = artifacts.get(g.getKey()); + // Check that no two artifacts are stored under the same file. + assert(f == null || f == g.getValue()); + if (f == null) { + f = g.getValue(); + artifacts.put(g.getKey(), g.getValue()); + } + } + } + } + } + + /** + * Collect all the artifacts of all modules and packages. + * + * @param m The set of modules. + */ + public void collectArtifacts(Map m) { + modules = m; + // Extract all the found packages. + for (Module i : modules.values()) { + for (Map.Entry j : i.packages().entrySet()) { + Package p = packages.get(j.getKey()); + // Check that no two different packages are stored under same name. + assert(p == null || p == j.getValue()); + p = j.getValue(); + packages.put(j.getKey(),j.getValue()); + for (Map.Entry g : p.artifacts().entrySet()) { + File f = artifacts.get(g.getKey()); + // Check that no two artifacts are stored under the same file. + assert(f == null || f == g.getValue()); + artifacts.put(g.getKey(), g.getValue()); + } + } + } + } + + /** + * Calculate the package dependents (ie the reverse of the dependencies). + */ + public void calculateDependents() { + dependents = new HashMap>(); + for (String s : packages.keySet()) { + Package p = packages.get(s); + for (String d : p.dependencies()) { + Set ss = dependents.get(d); + if (ss == null) { + ss = new HashSet(); + dependents.put(d, ss); + } + // Add the dependent information to the global dependent map. + ss.add(s); + Package dp = packages.get(d); + // Also add the dependent information to the package specific map. + // Normally, you do not compile java.lang et al. Therefore + // there are several packages that p depends upon that you + // do not have in your state database. This is perfectly fine. + if (dp != null) { + // But this package did exist in the state database. + dp.addDependent(p.name()); + } + } + } + } + + /** + * Verify that the setModules method above did the right thing when + * running through the module->package->source structure. + */ + public void checkInternalState(String msg, boolean linkedOnly, Map srcs) { + boolean baad = false; + Map original = new HashMap(); + Map calculated = new HashMap(); + + for (String s : sources.keySet()) { + Source ss = sources.get(s); + if (ss.isLinkedOnly() == linkedOnly) { + calculated.put(s,ss); + } + } + for (String s : srcs.keySet()) { + Source ss = srcs.get(s); + if (ss.isLinkedOnly() == linkedOnly) { + original.put(s,ss); + } + } + if (original.size() != calculated.size()) { + Log.error("INTERNAL ERROR "+msg+" original and calculated are not the same size!"); + baad = true; + } + if (!original.keySet().equals(calculated.keySet())) { + Log.error("INTERNAL ERROR "+msg+" original and calculated do not have the same domain!"); + baad = true; + } + if (!baad) { + for (String s : original.keySet()) { + Source s1 = original.get(s); + Source s2 = calculated.get(s); + if (s1 == null || s2 == null || !s1.equals(s2)) { + Log.error("INTERNAL ERROR "+msg+" original and calculated have differing elements for "+s); + } + baad = true; + } + } + if (baad) { + for (String s : original.keySet()) { + Source ss = original.get(s); + Source sss = calculated.get(s); + if (sss == null) { + Log.error("The file "+s+" does not exist in calculated tree of sources."); + } + } + for (String s : calculated.keySet()) { + Source ss = calculated.get(s); + Source sss = original.get(s); + if (sss == null) { + Log.error("The file "+s+" does not exist in original set of found sources."); + } + } + } + } + + /** + * Load a module from the javac state file. + */ + public Module loadModule(String l) { + Module m = Module.load(l); + modules.put(m.name(), m); + return m; + } + + /** + * Load a package from the javac state file. + */ + public Package loadPackage(Module lastModule, String l) { + Package p = Package.load(lastModule, l); + lastModule.addPackage(p); + packages.put(p.name(), p); + return p; + } + + /** + * Load a source from the javac state file. + */ + public Source loadSource(Package lastPackage, String l, boolean is_generated) { + Source s = Source.load(lastPackage, l, is_generated); + lastPackage.addSource(s); + sources.put(s.name(), s); + return s; + } + + /** + * During an incremental compile we need to copy the old javac state + * information about packages that were not recompiled. + */ + public void copyPackagesExcept(BuildState prev, Set recompiled, Set removed) { + for (String pkg : prev.packages().keySet()) { + // Do not copy recompiled or removed packages. + if (recompiled.contains(pkg) || removed.contains(pkg)) continue; + Module mnew = findModuleFromPackageName(pkg); + Package pprev = prev.packages().get(pkg); + mnew.addPackage(pprev); + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/CleanProperties.java b/langtools/src/share/classes/com/sun/tools/sjavac/CleanProperties.java new file mode 100644 index 00000000000..a46cd71806c --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/CleanProperties.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.*; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; + +/** + * The clean properties transform should not be necessary. + * Eventually we will cleanup the property file sources in the OpenJDK instead. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class CleanProperties implements Transformer +{ + public void setExtra(String e) { + // Any extra information is ignored for clean properties. + } + + public void setExtra(String[] a) { + // Any extra information is ignored for clean properties. + } + + public boolean transform(Map> pkgSrcs, + Set visibleSrcs, + Map> visibleClasses, + Map> oldPackageDependencies, + URI destRoot, + Map> packageArtifacts, + Map> packageDependencies, + Map packagePublicApis, + int debugLevel, + boolean incremental, + int numCores, + PrintStream out, + PrintStream err) + { + boolean rc = true; + for (String pkgName : pkgSrcs.keySet()) { + String pkgNameF = pkgName.replace('.',File.separatorChar); + for (URI u : pkgSrcs.get(pkgName)) { + File src = new File(u); + boolean r = clean(pkgName, pkgNameF, src, new File(destRoot), debugLevel, + packageArtifacts); + if (r == false) { + rc = false; + } + } + } + return rc; + } + + boolean clean(String pkgName, String pkgNameF, File src, File destRoot, int debugLevel, + Map> packageArtifacts) + { + // Load the properties file. + Properties p = new Properties(); + try { + p.load(new FileInputStream(src)); + } catch (IOException e) { + Log.error("Error reading file "+src.getPath()); + return false; + } + + // Sort the properties in increasing key order. + List sortedKeys = new ArrayList(); + for (Object key : p.keySet()) { + sortedKeys.add((String)key); + } + Collections.sort(sortedKeys); + Iterator keys = sortedKeys.iterator(); + + // Collect the properties into a string buffer. + StringBuilder data = new StringBuilder(); + while (keys.hasNext()) { + String key = keys.next(); + data.append(CompileProperties.escape(key)+":"+CompileProperties.escape((String)p.get(key))+"\n"); + } + + String destFilename = destRoot.getPath()+File.separator+pkgNameF+File.separator+src.getName(); + File dest = new File(destFilename); + + // Make sure the dest directories exist. + if (!dest.getParentFile().isDirectory()) { + if (!dest.getParentFile().mkdirs()) { + Log.error("Could not create the directory "+dest.getParentFile().getPath()); + return false; + } + } + + Set as = packageArtifacts.get(pkgName); + if (as == null) { + as = new HashSet(); + packageArtifacts.put(pkgName, as); + } + as.add(dest.toURI()); + + if (dest.exists() && dest.lastModified() > src.lastModified()) { + // A cleaned property file exists, and its timestamp is newer than the source. + // Assume that we do not need to clean! + // Thus we are done. + return true; + } + + Log.info("Cleaning property file "+pkgNameF+File.separator+src.getName()); + try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dest)))) { + writer.write(data.toString()); + } catch ( IOException e ) { + Log.error("Could not write file "+dest.getPath()); + return false; + } + return true; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/CompileChunk.java b/langtools/src/share/classes/com/sun/tools/sjavac/CompileChunk.java new file mode 100644 index 00000000000..54d5658d9b2 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/CompileChunk.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.net.URI; +import java.util.HashSet; +import java.util.Set; + +/** + * A compile chunk is a list of sources/packages to be compiled. Possibly a subset of + * the total number of sources/packages to be compiled for this sjavac invocation. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class CompileChunk implements Comparable { + public int numPackages; + public int numDependents; + public Set srcs = new HashSet(); + public StringBuilder pkgNames = new StringBuilder(); + public String pkgFromTos = ""; + + public int compareTo(CompileChunk c) { + if (numDependents == c.numDependents) return 0; + if (numDependents > c.numDependents) return -1; + return -1; + } + + boolean equal(CompileChunk c) { + return numDependents == c.numDependents; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java b/langtools/src/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java new file mode 100644 index 00000000000..d559de8a951 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.net.URI; +import java.util.Arrays; +import java.util.Random; +import java.util.Set; +import java.util.Map; + +import com.sun.tools.sjavac.server.JavacServer; +import com.sun.tools.sjavac.server.SysInfo; +import java.io.PrintStream; + +/** + * This transform compiles a set of packages containing Java sources. + * The compile request is divided into separate sets of source files. + * For each set a separate request thread is dispatched to a javac server + * and the meta data is accumulated. The number of sets correspond more or + * less to the number of cores. Less so now, than it will in the future. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class CompileJavaPackages implements Transformer { + + // The current limited sharing of data between concurrent JavaCompilers + // in the server will not give speedups above 3 cores. Thus this limit. + // We hope to improve this in the future. + final static int limitOnConcurrency = 3; + + String serverSettings; + public void setExtra(String e) { + serverSettings = e; + } + + String[] args; + public void setExtra(String[] a) { + args = a; + } + + public boolean transform(Map> pkgSrcs, + Set visibleSources, + Map> visibleClasses, + Map> oldPackageDependents, + URI destRoot, + final Map> packageArtifacts, + final Map> packageDependencies, + final Map packagePubapis, + int debugLevel, + boolean incremental, + int numCores, + PrintStream out, + PrintStream err) + { + boolean rc = true; + boolean concurrentCompiles = true; + + // Fetch the id. + String id = Util.extractStringOption("id", serverSettings); + if (id == null || id.equals("")) { + // No explicit id set. Create a random id so that the requests can be + // grouped properly in the server. + id = "id"+(((new Random()).nextLong())&Long.MAX_VALUE); + } + // Only keep portfile and sjavac settings.. + String psServerSettings = Util.cleanSubOptions("--server:", Util.set("portfile","sjavac","background","keepalive"), serverSettings); + + // Get maximum heap size from the server! + SysInfo sysinfo = JavacServer.connectGetSysInfo(psServerSettings, out, err); + if (sysinfo.numCores == -1) { + Log.error("Could not query server for sysinfo!"); + return false; + } + int numMBytes = (int)(sysinfo.maxMemory / ((long)(1024*1024))); + Log.debug("Server reports "+numMBytes+"MiB of memory and "+sysinfo.numCores+" cores"); + + if (numCores <= 0) { + // Set the requested number of cores to the number of cores on the server. + numCores = sysinfo.numCores; + Log.debug("Number of jobs not explicitly set, defaulting to "+sysinfo.numCores); + } else if (sysinfo.numCores < numCores) { + // Set the requested number of cores to the number of cores on the server. + Log.debug("Limiting jobs from explicitly set "+numCores+" to cores available on server: "+sysinfo.numCores); + numCores = sysinfo.numCores; + } else { + Log.debug("Number of jobs explicitly set to "+numCores); + } + // More than three concurrent cores does not currently give a speedup, at least for compiling the jdk + // in the OpenJDK. This will change in the future. + int numCompiles = numCores; + if (numCores > limitOnConcurrency) numCompiles = limitOnConcurrency; + // Split the work up in chunks to compiled. + + int numSources = 0; + for (String s : pkgSrcs.keySet()) { + Set ss = pkgSrcs.get(s); + numSources += ss.size(); + } + + int sourcesPerCompile = numSources / numCompiles; + + // For 64 bit Java, it seems we can compile the OpenJDK 8800 files with a 1500M of heap + // in a single chunk, with reasonable performance. + // For 32 bit java, it seems we need 1G of heap. + // Number experimentally determined when compiling the OpenJDK. + // Includes space for reasonably efficient garbage collection etc, + // Calculating backwards gives us a requirement of + // 1500M/8800 = 175 KiB for 64 bit platforms + // and 1G/8800 = 119 KiB for 32 bit platform + // for each compile..... + int kbPerFile = 175; + String osarch = System.getProperty("os.arch"); + if (osarch.equals("i386")) { + // For 32 bit platforms, assume it is slightly smaller + // because of smaller object headers and pointers. + kbPerFile = 119; + } + int numRequiredMBytes = (kbPerFile*numSources)/1024; + Log.debug("For os.arch "+osarch+" the empirically determined heap required per file is "+kbPerFile+"KiB"); + Log.debug("Server has "+numMBytes+"MiB of heap."); + Log.debug("Heuristics say that we need "+numRequiredMBytes+"MiB of heap for all source files."); + // Perform heuristics to see how many cores we can use, + // or if we have to the work serially in smaller chunks. + if (numMBytes < numRequiredMBytes) { + // Ouch, cannot fit even a single compile into the heap. + // Split it up into several serial chunks. + concurrentCompiles = false; + // Limit the number of sources for each compile to 500. + if (numSources < 500) { + numCompiles = 1; + sourcesPerCompile = numSources; + Log.debug("Compiling as a single source code chunk to stay within heap size limitations!"); + } else if (sourcesPerCompile > 500) { + // This number is very low, and tuned to dealing with the OpenJDK + // where the source is >very< circular! In normal application, + // with less circularity the number could perhaps be increased. + numCompiles = numSources / 500; + sourcesPerCompile = numSources/numCompiles; + Log.debug("Compiling source as "+numCompiles+" code chunks serially to stay within heap size limitations!"); + } + } else { + if (numCompiles > 1) { + // Ok, we can fit at least one full compilation on the heap. + float usagePerCompile = (float)numRequiredMBytes / ((float)numCompiles * (float)0.7); + int usage = (int)(usagePerCompile * (float)numCompiles); + Log.debug("Heuristics say that for "+numCompiles+" concurrent compiles we need "+usage+"MiB"); + if (usage > numMBytes) { + // Ouch it does not fit. Reduce to a single chunk. + numCompiles = 1; + sourcesPerCompile = numSources; + // What if the relationship betweem number of compile_chunks and num_required_mbytes + // is not linear? Then perhaps 2 chunks would fit where 3 does not. Well, this is + // something to experiment upon in the future. + Log.debug("Limiting compile to a single thread to stay within heap size limitations!"); + } + } + } + + Log.debug("Compiling sources in "+numCompiles+" chunk(s)"); + + // Create the chunks to be compiled. + final CompileChunk[] compileChunks = createCompileChunks(pkgSrcs, oldPackageDependents, + numCompiles, sourcesPerCompile); + + if (Log.isDebugging()) { + int cn = 1; + for (CompileChunk cc : compileChunks) { + Log.debug("Chunk "+cn+" for "+id+" ---------------"); + cn++; + for (URI u : cc.srcs) { + Log.debug(""+u); + } + } + } + + // The return values for each chunked compile. + final int[] rn = new int[numCompiles]; + // The requets, might or might not run as a background thread. + final Thread[] requests = new Thread[numCompiles]; + + final Set fvisible_sources = visibleSources; + final Map> fvisible_classes = visibleClasses; + + long start = System.currentTimeMillis(); + + for (int i=0; i 0) { + String numdeps = ""; + if (cc.numDependents > 0) numdeps = "(with "+cc.numDependents+" dependents) "; + if (!incremental || cc.numPackages > 16) { + String info = "("+cc.pkgFromTos+")"; + if (info.equals("( to )")) { + info = ""; + } + Log.info("Compiling "+cc.srcs.size()+" files "+numdeps+"in "+cc.numPackages+" packages "+info); + } else { + Log.info("Compiling "+cc.pkgNames+numdeps); + } + if (concurrentCompiles) { + requests[ii].start(); + } + else { + requests[ii].run(); + // If there was an error, then stop early when running single threaded. + if (rn[i] != 0) { + return false; + } + } + } + } + if (concurrentCompiles) { + // If there are background threads for the concurrent compiles, then join them. + for (int i=0; i 0) { + if (rn[i] != 0) { + rc = false; + } + } + } + long duration = System.currentTimeMillis() - start; + long minutes = duration/60000; + long seconds = (duration-minutes*60000)/1000; + Log.debug("Compilation of "+numSources+" source files took "+minutes+"m "+seconds+"s"); + + return rc; + } + + + /** + * Split up the sources into compile chunks. If old package dependents information + * is available, sort the order of the chunks into the most dependent first! + * (Typically that chunk contains the java.lang package.) In the future + * we could perhaps improve the heuristics to put the sources into even more sensible chunks. + * Now the package are simple sorted in alphabetical order and chunked, then the chunks + * are sorted on how dependent they are. + * + * @param pkgSrcs The sources to compile. + * @param oldPackageDependents Old package dependents, if non-empty, used to sort the chunks. + * @param numCompiles The number of chunks. + * @param sourcesPerCompile The number of sources per chunk. + * @return + */ + CompileChunk[] createCompileChunks(Map> pkgSrcs, + Map> oldPackageDependents, + int numCompiles, + int sourcesPerCompile) { + + CompileChunk[] compileChunks = new CompileChunk[numCompiles]; + for (int i=0; i s = pkgSrcs.get(pkgName); + if (cc.srcs.size()+s.size() > sourcesPerCompile && ci < numCompiles-1) { + from = null; + ci++; + cc = compileChunks[ci]; + } + cc.numPackages++; + cc.srcs.addAll(s); + + // Calculate nice package names to use as information when compiling. + String justPkgName = Util.justPackageName(pkgName); + // Fetch how many packages depend on this package from the old build state. + Set ss = oldPackageDependents.get(pkgName); + if (ss != null) { + // Accumulate this information onto this chunk. + cc.numDependents += ss.size(); + } + if (from == null || from.trim().equals("")) from = justPkgName; + cc.pkgNames.append(justPkgName+"("+s.size()+") "); + cc.pkgFromTos = from+" to "+justPkgName; + } + // If we are compiling serially, sort the chunks, so that the chunk (with the most dependents) (usually the chunk + // containing java.lang.Object, is to be compiled first! + // For concurrent compilation, this does not matter. + Arrays.sort(compileChunks); + return compileChunks; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/CompileProperties.java b/langtools/src/share/classes/com/sun/tools/sjavac/CompileProperties.java new file mode 100644 index 00000000000..ce043817733 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/CompileProperties.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.*; +import java.net.URI; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.HashSet; +import java.util.Map; + +/** + * Compile properties transform a properties file into a Java source file. + * Java has built in support for reading properties from either a text file + * in the source or a compiled java source file. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class CompileProperties implements Transformer +{ + // Any extra information passed from the command line, for example if: + // -tr .proppp=com.sun.tools.javac.smart.CompileProperties,sun.util.resources.LocaleNamesBundle + // then extra will be "sun.util.resources.LocaleNamesBundle" + String extra; + + public void setExtra(String e) { + extra = e; + } + + public void setExtra(String[] a) { + } + + public boolean transform(Map> pkgSrcs, + Set visibleSrcs, + Map> visibleClasses, + Map> oldPackageDependents, + URI destRoot, + Map> packageArtifacts, + Map> packageDependencies, + Map packagePublicApis, + int debugLevel, + boolean incremental, + int numCores, + PrintStream out, + PrintStream err) { + boolean rc = true; + for (String pkgName : pkgSrcs.keySet()) { + String pkgNameF = Util.toFileSystemPath(pkgName); + for (URI u : pkgSrcs.get(pkgName)) { + File src = new File(u); + boolean r = compile(pkgName, pkgNameF, src, new File(destRoot), debugLevel, + packageArtifacts); + if (r == false) { + rc = false; + } + } + } + return rc; + } + + boolean compile(String pkgName, String pkgNameF, File src, File destRoot, int debugLevel, + Map> packageArtifacts) + { + String superClass = "java.util.ListResourceBundle"; + + if (extra != null) { + superClass = extra; + } + // Load the properties file. + Properties p = new Properties(); + try { + p.load(new FileInputStream(src)); + } catch (IOException e) { + Log.error("Error reading file "+src.getPath()); + return false; + } + + // Calculate the name of the Java source file to be generated. + int dp = src.getName().lastIndexOf("."); + String classname = src.getName().substring(0,dp); + + // Sort the properties in increasing key order. + List sortedKeys = new ArrayList(); + for (Object key : p.keySet()) { + sortedKeys.add((String)key); + } + Collections.sort(sortedKeys); + Iterator keys = sortedKeys.iterator(); + + // Collect the properties into a string buffer. + StringBuilder data = new StringBuilder(); + while (keys.hasNext()) { + String key = keys.next(); + data.append(" { \"" + escape(key) + "\", \"" + + escape((String)p.get(key)) + "\" },\n"); + } + + // Create dest file name. It is derived from the properties file name. + String destFilename = destRoot.getPath()+File.separator+pkgNameF+File.separator+classname+".java"; + File dest = new File(destFilename); + + // Make sure the dest directories exist. + if (!dest.getParentFile().isDirectory()) { + if (!dest.getParentFile().mkdirs()) { + Log.error("Could not create the directory "+dest.getParentFile().getPath()); + return false; + } + } + + Set as = packageArtifacts.get(pkgName); + if (as == null) { + as = new HashSet(); + packageArtifacts.put(pkgName, as); + } + as.add(dest.toURI()); + + if (dest.exists() && dest.lastModified() > src.lastModified()) { + // A generated file exists, and its timestamp is newer than the source. + // Assume that we do not need to regenerate the dest file! + // Thus we are done. + return true; + } + + String packageString = "package " + pkgNameF.replace(File.separatorChar,'.') + ";\n\n"; + + Log.info("Compiling property file "+pkgNameF+File.separator+src.getName()); + try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dest)))) { + MessageFormat format = new MessageFormat(FORMAT); + writer.write(format.format(new Object[] { packageString, classname, superClass, data })); + } catch ( IOException e ) { + Log.error("Could not write file "+dest.getPath()); + return false; + } + return true; + } + + private static final String FORMAT = + "{0}" + + "public final class {1} extends {2} '{'\n" + + " protected final Object[][] getContents() '{'\n" + + " return new Object[][] '{'\n" + + "{3}" + + " };\n" + + " }\n" + + "}\n"; + + public static String escape(String theString) { + int len = theString.length(); + StringBuilder outBuffer = new StringBuilder(len*2); + + for(int x=0; x 0x007e)) { + outBuffer.append('\\'); + outBuffer.append('u'); + outBuffer.append(toHex((aChar >> 12) & 0xF)); + outBuffer.append(toHex((aChar >> 8) & 0xF)); + outBuffer.append(toHex((aChar >> 4) & 0xF)); + outBuffer.append(toHex( aChar & 0xF)); + } else { + if (aChar == '"') { + outBuffer.append('\\'); + } + outBuffer.append(aChar); + } + } + } + return outBuffer.toString(); + } + + private static char toHex(int nibble) { + return hexDigit[(nibble & 0xF)]; + } + + private static final char[] hexDigit = { + '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' + }; +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/CopyFile.java b/langtools/src/share/classes/com/sun/tools/sjavac/CopyFile.java new file mode 100644 index 00000000000..c131ed3a1f3 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/CopyFile.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.*; +import java.net.URI; +import java.util.Set; +import java.util.HashSet; +import java.util.Map; + +/** + * The copy file transform simply copies a matching file from -src to -d . + * Such files are typically images, xml documents and other data files. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class CopyFile implements Transformer { + + public void setExtra(String e) { + } + + public void setExtra(String[] a) { + } + + public boolean transform(Map> pkgSrcs, + Set visibleSrcs, + Map> visibleClasses, + Map> oldPackageDependents, + URI destRoot, + Map> packageArtifacts, + Map> packageDependencies, + Map packagePubapis, + int debugLevel, + boolean incremental, + int numCores, + PrintStream out, + PrintStream err) + { + boolean rc = true; + String dest_filename; + File dest; + + for (String pkgName : pkgSrcs.keySet()) { + String pkgNameF = Util.toFileSystemPath(pkgName); + for (URI u : pkgSrcs.get(pkgName)) { + File src = new File(u); + File destDir; + destDir = new File(destRoot.getPath()+File.separator+pkgNameF); + dest_filename = destRoot.getPath()+File.separator+pkgNameF+File.separator+src.getName(); + dest = new File(dest_filename); + + if (!destDir.isDirectory()) { + if (!destDir.mkdirs()) { + Log.error("Error: The copier could not create the directory "+ + destDir.getPath()); + return false; + } + } + + Set as = packageArtifacts.get(pkgName); + if (as == null) { + as = new HashSet(); + packageArtifacts.put(pkgName, as); + } + as.add(dest.toURI()); + + if (dest.exists() && dest.lastModified() > src.lastModified()) { + // A copied file exists, and its timestamp is newer than the source. + continue; + } + + Log.info("Copying "+pkgNameF+File.separator+src.getName()); + + try (InputStream fin = new FileInputStream(src); + OutputStream fout = new FileOutputStream(dest)) { + byte[] buf = new byte[1024]; + int len; + while ((len = fin.read(buf)) > 0){ + fout.write(buf, 0, len); + } + } + catch(IOException e){ + Log.error("Could not copy the file "+src.getPath()+" to "+dest.getPath()); + rc = false; + } + } + } + return rc; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/JavacState.java b/langtools/src/share/classes/com/sun/tools/sjavac/JavacState.java new file mode 100644 index 00000000000..7e1af207eab --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/JavacState.java @@ -0,0 +1,857 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.*; +import java.util.Collections; +import java.util.Date; +import java.util.Set; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.text.SimpleDateFormat; +import java.net.URI; +import java.util.*; + +/** + * The javac state class maintains the previous (prev) and the current (now) + * build states and everything else that goes into the javac_state file. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class JavacState +{ + // The arguments to the compile. If not identical, then it cannot + // be an incremental build! + String theArgs; + // The number of cores limits how many threads are used for heavy concurrent work. + int numCores; + + // The bin_dir/javac_state + private String javacStateFilename; + private File javacState; + + // The previous build state is loaded from javac_state + private BuildState prev; + // The current build state is constructed during the build, + // then saved as the new javac_state. + private BuildState now; + + // Something has changed in the javac_state. It needs to be saved! + private boolean needsSaving; + // If this is a new javac_state file, then do not print unnecessary messages. + private boolean newJavacState; + + // These are packages where something has changed and the package + // needs to be recompiled. Actions that trigger recompilation: + // * source belonging to the package has changed + // * artifact belonging to the package is lost, or its timestamp has been changed. + // * an unknown artifact has appeared, we simply delete it, but we also trigger a recompilation. + // * a package that is tainted, taints all packages that depend on it. + private Set taintedPackages; + // After a compile, the pubapis are compared with the pubapis stored in the javac state file. + // Any packages where the pubapi differ are added to this set. + // Later we use this set and the dependency information to taint dependent packages. + private Set packagesWithChangedPublicApis; + // When a module-info.java file is changed, taint the module, + // then taint all modules that depend on that that module. + // A module dependency can occur directly through a require, or + // indirectly through a module that does a public export for the first tainted module. + // When all modules are tainted, then taint all packages belonging to these modules. + // Then rebuild. It is perhaps possible (and valuable?) to do a more finegrained examination of the + // change in module-info.java, but that will have to wait. + private Set taintedModules; + // The set of all packages that has been recompiled. + // Copy over the javac_state for the packages that did not need recompilation, + // verbatim from the previous (prev) to the new (now) build state. + private Set recompiledPackages; + + // The output directories filled with tasty artifacts. + private File binDir, gensrcDir, headerDir; + + // The current status of the file system. + private Set binArtifacts; + private Set gensrcArtifacts; + private Set headerArtifacts; + + // The status of the sources. + Set removedSources = null; + Set addedSources = null; + Set modifiedSources = null; + + // Visible sources for linking. These are the only + // ones that -sourcepath is allowed to see. + Set visibleSrcs; + + // Visible classes for linking. These are the only + // ones that -classpath is allowed to see. + // It maps from a classpath root to the set of visible classes for that root. + // If the set is empty, then all classes are visible for that root. + // It can also map from a jar file to the set of visible classes for that jar file. + Map> visibleClasses; + + // Setup two transforms that always exist. + private CopyFile copyFiles = new CopyFile(); + private CompileJavaPackages compileJavaPackages = new CompileJavaPackages(); + + // Where to send stdout and stderr. + private PrintStream out, err; + + JavacState(String[] args, File bd, File gd, File hd, boolean permitUnidentifiedArtifacts, boolean removeJavacState, + PrintStream o, PrintStream e) { + out = o; + err = e; + numCores = Main.findNumberOption(args, "-j"); + theArgs = ""; + for (String a : removeArgsNotAffectingState(args)) { + theArgs = theArgs+a+" "; + } + binDir = bd; + gensrcDir = gd; + headerDir = hd; + javacStateFilename = binDir.getPath()+File.separator+"javac_state"; + javacState = new File(javacStateFilename); + if (removeJavacState && javacState.exists()) { + javacState.delete(); + } + newJavacState = false; + if (!javacState.exists()) { + newJavacState = true; + // If there is no javac_state then delete the contents of all the artifact dirs! + // We do not want to risk building a broken incremental build. + // BUT since the makefiles still copy things straight into the bin_dir et al, + // we avoid deleting files here, if the option --permit-unidentified-classes was supplied. + if (!permitUnidentifiedArtifacts) { + deleteContents(binDir); + deleteContents(gensrcDir); + deleteContents(headerDir); + } + needsSaving = true; + } + prev = new BuildState(); + now = new BuildState(); + taintedPackages = new HashSet(); + recompiledPackages = new HashSet(); + packagesWithChangedPublicApis = new HashSet(); + } + + public BuildState prev() { return prev; } + public BuildState now() { return now; } + + /** + * Remove args not affecting the state. + */ + static String[] removeArgsNotAffectingState(String[] args) { + String[] out = new String[args.length]; + int j = 0; + for (int i = 0; i vs) { + visibleSrcs = new HashSet(); + for (String s : vs.keySet()) { + Source src = vs.get(s); + visibleSrcs.add(src.file().toURI()); + } + } + + /** + * Specify which classes are visible to the compiler through -classpath. + */ + public void setVisibleClasses(Map vs) { + visibleSrcs = new HashSet(); + for (String s : vs.keySet()) { + Source src = vs.get(s); + visibleSrcs.add(src.file().toURI()); + } + } + /** + * Returns true if this is an incremental build. + */ + public boolean isIncremental() { + return !prev.sources().isEmpty(); + } + + /** + * Find all artifacts that exists on disk. + */ + public void findAllArtifacts() { + binArtifacts = findAllFiles(binDir); + gensrcArtifacts = findAllFiles(gensrcDir); + headerArtifacts = findAllFiles(headerDir); + } + + /** + * Lookup the artifacts generated for this package in the previous build. + */ + private Map fetchPrevArtifacts(String pkg) { + Package p = prev.packages().get(pkg); + if (p != null) { + return p.artifacts(); + } + return new HashMap(); + } + + /** + * Delete all prev artifacts in the currently tainted packages. + */ + public void deleteClassArtifactsInTaintedPackages() { + for (String pkg : taintedPackages) { + Map arts = fetchPrevArtifacts(pkg); + for (File f : arts.values()) { + if (f.exists() && f.getName().endsWith(".class")) { + f.delete(); + } + } + } + } + + /** + * Mark the javac_state file to be in need of saving and as a side effect, + * it gets a new timestamp. + */ + private void needsSaving() { + needsSaving = true; + } + + /** + * Save the javac_state file. + */ + public void save() throws IOException { + if (!needsSaving) return; + try (FileWriter out = new FileWriter(javacStateFilename)) { + StringBuilder b = new StringBuilder(); + long millisNow = System.currentTimeMillis(); + Date d = new Date(millisNow); + SimpleDateFormat df = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); + b.append("# javac_state ver 0.3 generated "+millisNow+" "+df.format(d)+"\n"); + b.append("# This format might change at any time. Please do not depend on it.\n"); + b.append("# M module\n"); + b.append("# P package\n"); + b.append("# S C source_tobe_compiled timestamp\n"); + b.append("# S L link_only_source timestamp\n"); + b.append("# G C generated_source timestamp\n"); + b.append("# A artifact timestamp\n"); + b.append("# D dependency\n"); + b.append("# I pubapi\n"); + b.append("# R arguments\n"); + b.append("R ").append(theArgs).append("\n"); + + // Copy over the javac_state for the packages that did not need recompilation. + now.copyPackagesExcept(prev, recompiledPackages, new HashSet()); + // Save the packages, ie package names, dependencies, pubapis and artifacts! + // I.e. the lot. + Module.saveModules(now.modules(), b); + + String s = b.toString(); + out.write(s, 0, s.length()); + } + } + + /** + * Load a javac_state file. + */ + public static JavacState load(String[] args, File binDir, File gensrcDir, File headerDir, + boolean permitUnidentifiedArtifacts, PrintStream out, PrintStream err) { + JavacState db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, false, out, err); + Module lastModule = null; + Package lastPackage = null; + Source lastSource = null; + boolean noFileFound = false; + boolean foundCorrectVerNr = false; + boolean newCommandLine = false; + boolean syntaxError = false; + + try (BufferedReader in = new BufferedReader(new FileReader(db.javacStateFilename))) { + for (;;) { + String l = in.readLine(); + if (l==null) break; + if (l.length()>=3 && l.charAt(1) == ' ') { + char c = l.charAt(0); + if (c == 'M') { + lastModule = db.prev.loadModule(l); + } else + if (c == 'P') { + if (lastModule == null) { syntaxError = true; break; } + lastPackage = db.prev.loadPackage(lastModule, l); + } else + if (c == 'D') { + if (lastModule == null || lastPackage == null) { syntaxError = true; break; } + lastPackage.loadDependency(l); + } else + if (c == 'I') { + if (lastModule == null || lastPackage == null) { syntaxError = true; break; } + lastPackage.loadPubapi(l); + } else + if (c == 'A') { + if (lastModule == null || lastPackage == null) { syntaxError = true; break; } + lastPackage.loadArtifact(l); + } else + if (c == 'S') { + if (lastModule == null || lastPackage == null) { syntaxError = true; break; } + lastSource = db.prev.loadSource(lastPackage, l, false); + } else + if (c == 'G') { + if (lastModule == null || lastPackage == null) { syntaxError = true; break; } + lastSource = db.prev.loadSource(lastPackage, l, true); + } else + if (c == 'R') { + String ncmdl = "R "+db.theArgs; + if (!l.equals(ncmdl)) { + newCommandLine = true; + } + } else + if (c == '#') { + if (l.startsWith("# javac_state ver ")) { + int sp = l.indexOf(" ", 18); + if (sp != -1) { + String ver = l.substring(18,sp); + if (!ver.equals("0.3")) { + break; + } + foundCorrectVerNr = true; + } + } + } + } + } + } catch (FileNotFoundException e) { + // Silently create a new javac_state file. + noFileFound = true; + } catch (IOException e) { + Log.info("Dropping old javac_state because of errors when reading it."); + db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, true, out, err); + foundCorrectVerNr = true; + newCommandLine = false; + syntaxError = false; + } + if (foundCorrectVerNr == false && !noFileFound) { + Log.info("Dropping old javac_state since it is of an old version."); + db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, true, out, err); + } else + if (newCommandLine == true && !noFileFound) { + Log.info("Dropping old javac_state since a new command line is used!"); + db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, true, out, err); + } else + if (syntaxError == true) { + Log.info("Dropping old javac_state since it contains syntax errors."); + db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, true, out, err); + } + db.prev.calculateDependents(); + return db; + } + + /** + * Mark a java package as tainted, ie it needs recompilation. + */ + public void taintPackage(String name, String because) { + if (!taintedPackages.contains(name)) { + if (because != null) Log.debug("Tainting "+Util.justPackageName(name)+" because "+because); + // It has not been tainted before. + taintedPackages.add(name); + needsSaving(); + Package nowp = now.packages().get(name); + if (nowp != null) { + for (String d : nowp.dependents()) { + taintPackage(d, because); + } + } + } + } + + /** + * This packages need recompilation. + */ + public Set taintedPackages() { + return taintedPackages; + } + + /** + * Clean out the tainted package set, used after the first round of compiles, + * prior to propagating dependencies. + */ + public void clearTaintedPackages() { + taintedPackages = new HashSet(); + } + + /** + * Go through all sources and check which have been removed, added or modified + * and taint the corresponding packages. + */ + public void checkSourceStatus(boolean check_gensrc) { + removedSources = calculateRemovedSources(); + for (Source s : removedSources) { + if (!s.isGenerated() || check_gensrc) { + taintPackage(s.pkg().name(), "source "+s.name()+" was removed"); + } + } + + addedSources = calculateAddedSources(); + for (Source s : addedSources) { + String msg = null; + if (isIncremental()) { + // When building from scratch, there is no point + // printing "was added" for every file since all files are added. + // However for an incremental build it makes sense. + msg = "source "+s.name()+" was added"; + } + if (!s.isGenerated() || check_gensrc) { + taintPackage(s.pkg().name(), msg); + } + } + + modifiedSources = calculateModifiedSources(); + for (Source s : modifiedSources) { + if (!s.isGenerated() || check_gensrc) { + taintPackage(s.pkg().name(), "source "+s.name()+" was modified"); + } + } + } + + /** + * Acquire the compile_java_packages suffix rule for .java files. + */ + public Map getJavaSuffixRule() { + Map sr = new HashMap(); + sr.put(".java", compileJavaPackages); + return sr; + } + + /** + * Acquire the copying transform. + */ + public Transformer getCopier() { + return copyFiles; + } + + /** + * If artifacts have gone missing, force a recompile of the packages + * they belong to. + */ + public void taintPackagesThatMissArtifacts() { + for (Package pkg : prev.packages().values()) { + for (File f : pkg.artifacts().values()) { + if (!f.exists()) { + // Hmm, the artifact on disk does not exist! Someone has removed it.... + // Lets rebuild the package. + taintPackage(pkg.name(), ""+f+" is missing."); + } + } + } + } + + /** + * Propagate recompilation through the dependency chains. + * Avoid re-tainting packages that have already been compiled. + */ + public void taintPackagesDependingOnChangedPackages(Set pkgs, Set recentlyCompiled) { + for (Package pkg : prev.packages().values()) { + for (String dep : pkg.dependencies()) { + if (pkgs.contains(dep) && !recentlyCompiled.contains(pkg.name())) { + taintPackage(pkg.name(), " its depending on "+dep); + } + } + } + } + + /** + * Scan all output dirs for artifacts and remove those files (artifacts?) + * that are not recognized as such, in the javac_state file. + */ + public void removeUnidentifiedArtifacts() { + Set allKnownArtifacts = new HashSet(); + for (Package pkg : prev.packages().values()) { + for (File f : pkg.artifacts().values()) { + allKnownArtifacts.add(f); + } + } + // Do not forget about javac_state.... + allKnownArtifacts.add(javacState); + + for (File f : binArtifacts) { + if (!allKnownArtifacts.contains(f)) { + Log.debug("Removing "+f.getPath()+" since it is unknown to the javac_state."); + f.delete(); + } + } + for (File f : headerArtifacts) { + if (!allKnownArtifacts.contains(f)) { + Log.debug("Removing "+f.getPath()+" since it is unknown to the javac_state."); + f.delete(); + } + } + for (File f : gensrcArtifacts) { + if (!allKnownArtifacts.contains(f)) { + Log.debug("Removing "+f.getPath()+" since it is unknown to the javac_state."); + f.delete(); + } + } + } + + /** + * Remove artifacts that are no longer produced when compiling! + */ + public void removeSuperfluousArtifacts(Set recentlyCompiled) { + // Nothing to do, if nothing was recompiled. + if (recentlyCompiled.size() == 0) return; + + for (String pkg : now.packages().keySet()) { + // If this package has not been recompiled, skip the check. + if (!recentlyCompiled.contains(pkg)) continue; + Collection arts = now.artifacts().values(); + for (File f : fetchPrevArtifacts(pkg).values()) { + if (!arts.contains(f)) { + Log.debug("Removing "+f.getPath()+" since it is now superfluous!"); + if (f.exists()) f.delete(); + } + } + } + } + + /** + * Return those files belonging to prev, but not now. + */ + private Set calculateRemovedSources() { + Set removed = new HashSet(); + for (String src : prev.sources().keySet()) { + if (now.sources().get(src) == null) { + removed.add(prev.sources().get(src)); + } + } + return removed; + } + + /** + * Return those files belonging to now, but not prev. + */ + private Set calculateAddedSources() { + Set added = new HashSet(); + for (String src : now.sources().keySet()) { + if (prev.sources().get(src) == null) { + added.add(now.sources().get(src)); + } + } + return added; + } + + /** + * Return those files where the timestamp is newer. + * If a source file timestamp suddenly is older than what is known + * about it in javac_state, then consider it modified, but print + * a warning! + */ + private Set calculateModifiedSources() { + Set modified = new HashSet(); + for (String src : now.sources().keySet()) { + Source n = now.sources().get(src); + Source t = prev.sources().get(src); + if (prev.sources().get(src) != null) { + if (t != null) { + if (n.lastModified() > t.lastModified()) { + modified.add(n); + } else if (n.lastModified() < t.lastModified()) { + modified.add(n); + Log.warn("The source file "+n.name()+" timestamp has moved backwards in time."); + } + } + } + } + return modified; + } + + /** + * Recursively delete a directory and all its contents. + */ + private static void deleteContents(File dir) { + if (dir != null && dir.exists()) { + for (File f : dir.listFiles()) { + if (f.isDirectory()) { + deleteContents(f); + } + f.delete(); + } + } + } + + /** + * Run the copy translator only. + */ + public void performCopying(File binDir, Map suffixRules) { + Map sr = new HashMap(); + for (Map.Entry e : suffixRules.entrySet()) { + if (e.getValue() == copyFiles) { + sr.put(e.getKey(), e.getValue()); + } + } + perform(binDir, sr); + } + + /** + * Run all the translators that translate into java source code. + * I.e. all translators that are not copy nor compile_java_source. + */ + public void performTranslation(File gensrcDir, Map suffixRules) { + Map sr = new HashMap(); + for (Map.Entry e : suffixRules.entrySet()) { + if (e.getValue() != copyFiles && + e.getValue() != compileJavaPackages) { + sr.put(e.getKey(), e.getValue()); + } + } + perform(gensrcDir, sr); + } + + /** + * Compile all the java sources. Return true, if it needs to be called again! + */ + public boolean performJavaCompilations(File binDir, + String serverSettings, + String[] args, + Set recentlyCompiled, + boolean[] rcValue) { + Map suffixRules = new HashMap(); + suffixRules.put(".java", compileJavaPackages); + compileJavaPackages.setExtra(serverSettings); + compileJavaPackages.setExtra(args); + + rcValue[0] = perform(binDir, suffixRules); + recentlyCompiled.addAll(taintedPackages()); + clearTaintedPackages(); + boolean again = !packagesWithChangedPublicApis.isEmpty(); + taintPackagesDependingOnChangedPackages(packagesWithChangedPublicApis, recentlyCompiled); + packagesWithChangedPublicApis = new HashSet(); + return again && rcValue[0]; + } + + /** + * Store the source into the set of sources belonging to the given transform. + */ + private void addFileToTransform(Map>> gs, Transformer t, Source s) { + Map> fs = gs.get(t); + if (fs == null) { + fs = new HashMap>(); + gs.put(t, fs); + } + Set ss = fs.get(s.pkg().name()); + if (ss == null) { + ss = new HashSet(); + fs.put(s.pkg().name(), ss); + } + ss.add(s.file().toURI()); + } + + /** + * For all packages, find all sources belonging to the package, group the sources + * based on their transformers and apply the transformers on each source code group. + */ + private boolean perform(File outputDir, Map suffixRules) + { + boolean rc = true; + // Group sources based on transforms. A source file can only belong to a single transform. + Map>> groupedSources = new HashMap>>(); + for (Source src : now.sources().values()) { + Transformer t = suffixRules.get(src.suffix()); + if (t != null) { + if (taintedPackages.contains(src.pkg().name()) && !src.isLinkedOnly()) { + addFileToTransform(groupedSources, t, src); + } + } + } + // Go through the transforms and transform them. + for (Map.Entry>> e : groupedSources.entrySet()) { + Transformer t = e.getKey(); + Map> srcs = e.getValue(); + // These maps need to be synchronized since multiple threads will be writing results into them. + Map> packageArtifacts = Collections.synchronizedMap(new HashMap>()); + Map> packageDependencies = Collections.synchronizedMap(new HashMap>()); + Map packagePublicApis = Collections.synchronizedMap(new HashMap()); + + boolean r = t.transform(srcs, + visibleSrcs, + visibleClasses, + prev.dependents(), + outputDir.toURI(), + packageArtifacts, + packageDependencies, + packagePublicApis, + 0, + isIncremental(), + numCores, + out, + err); + if (!r) rc = false; + + for (String p : srcs.keySet()) { + recompiledPackages.add(p); + } + // The transform is done! Extract all the artifacts and store the info into the Package objects. + for (Map.Entry> a : packageArtifacts.entrySet()) { + Module mnow = now.findModuleFromPackageName(a.getKey()); + mnow.addArtifacts(a.getKey(), a.getValue()); + } + // Extract all the dependencies and store the info into the Package objects. + for (Map.Entry> a : packageDependencies.entrySet()) { + Set deps = a.getValue(); + Module mnow = now.findModuleFromPackageName(a.getKey()); + mnow.setDependencies(a.getKey(), deps); + } + // Extract all the pubapis and store the info into the Package objects. + for (Map.Entry a : packagePublicApis.entrySet()) { + Module mprev = prev.findModuleFromPackageName(a.getKey()); + List pubapi = Package.pubapiToList(a.getValue()); + Module mnow = now.findModuleFromPackageName(a.getKey()); + mnow.setPubapi(a.getKey(), pubapi); + if (mprev.hasPubapiChanged(a.getKey(), pubapi)) { + // Aha! The pubapi of this package has changed! + // It can also be a new compile from scratch. + if (mprev.lookupPackage(a.getKey()).existsInJavacState()) { + // This is an incremental compile! The pubapi + // did change. Trigger recompilation of dependents. + packagesWithChangedPublicApis.add(a.getKey()); + Log.info("The pubapi of "+Util.justPackageName(a.getKey())+" has changed!"); + } + } + } + } + return rc; + } + + /** + * Utility method to recursively find all files below a directory. + */ + private static Set findAllFiles(File dir) { + Set foundFiles = new HashSet(); + if (dir == null) { + return foundFiles; + } + recurse(dir, foundFiles); + return foundFiles; + } + + private static void recurse(File dir, Set foundFiles) { + for (File f : dir.listFiles()) { + if (f.isFile()) { + foundFiles.add(f); + } else if (f.isDirectory()) { + recurse(f, foundFiles); + } + } + } + + /** + * Compare the calculate source list, with an explicit list, usually supplied from the makefile. + * Used to detect bugs where the makefile and sjavac have different opinions on which files + * should be compiled. + */ + public void compareWithMakefileList(File makefileSourceList) + throws ProblemException + { + // If we are building on win32 using for example cygwin the paths in the makefile source list + // might be /cygdrive/c/.... which does not match c:\.... + // We need to adjust our calculated sources to be identical, if necessary. + boolean mightNeedRewriting = File.pathSeparatorChar == ';'; + + if (makefileSourceList == null) return; + + Set calculatedSources = new HashSet(); + Set listedSources = new HashSet(); + + // Create a set of filenames with full paths. + for (Source s : now.sources().values()) { + calculatedSources.add(s.file().getPath()); + } + // Read in the file and create another set of filenames with full paths. + try { + BufferedReader in = new BufferedReader(new FileReader(makefileSourceList)); + for (;;) { + String l = in.readLine(); + if (l==null) break; + l = l.trim(); + if (mightNeedRewriting) { + if (l.indexOf(":") == 1 && l.indexOf("\\") == 2) { + // Everything a-ok, the format is already C:\foo\bar + } else if (l.indexOf(":") == 1 && l.indexOf("/") == 2) { + // The format is C:/foo/bar, rewrite into the above format. + l = l.replaceAll("/","\\\\"); + } else if (l.charAt(0) == '/' && l.indexOf("/",1) != -1) { + // The format might be: /cygdrive/c/foo/bar, rewrite into the above format. + // Do not hardcode the name cygdrive here. + int slash = l.indexOf("/",1); + l = l.replaceAll("/","\\\\"); + l = ""+l.charAt(slash+1)+":"+l.substring(slash+2); + } + if (Character.isLowerCase(l.charAt(0))) { + l = Character.toUpperCase(l.charAt(0))+l.substring(1); + } + } + listedSources.add(l); + } + } catch (FileNotFoundException e) { + throw new ProblemException("Could not open "+makefileSourceList.getPath()+" since it does not exist!"); + } catch (IOException e) { + throw new ProblemException("Could not read "+makefileSourceList.getPath()); + } + + for (String s : listedSources) { + if (!calculatedSources.contains(s)) { + throw new ProblemException("The makefile listed source "+s+" was not calculated by the smart javac wrapper!"); + } + } + + for (String s : calculatedSources) { + if (!listedSources.contains(s)) { + throw new ProblemException("The smart javac wrapper calculated source "+s+" was not listed by the makefiles!"); + } + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/Log.java b/langtools/src/share/classes/com/sun/tools/sjavac/Log.java new file mode 100644 index 00000000000..99bd29f2524 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/Log.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.PrintStream; + +/** + * Utility class only for sjavac logging. + * The log level can be set using for example --log=DEBUG on the sjavac command line. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class Log { + private static PrintStream out, err; + + public final static int WARN = 1; + public final static int INFO = 2; + public final static int DEBUG = 3; + public final static int TRACE = 4; + private static int level = WARN; + + static public void trace(String msg) { + if (level >= TRACE) { + out.println(msg); + } + } + + static public void debug(String msg) { + if (level >= DEBUG) { + out.println(msg); + } + } + + static public void info(String msg) { + if (level >= INFO) { + out.println(msg); + } + } + + static public void warn(String msg) { + err.println(msg); + } + + static public void error(String msg) { + err.println(msg); + } + + static public void setLogLevel(String l, PrintStream o, PrintStream e) + throws ProblemException { + out = o; + err = e; + if (l.equals("warn")) level = WARN; + else if (l.equals("info")) level = INFO; + else if (l.equals("debug")) level = DEBUG; + else if (l.equals("trace")) level = TRACE; + else throw new ProblemException("No such log level \""+l+"\""); + } + + static public boolean isTracing() { + return level >= TRACE; + } + + static public boolean isDebugging() { + return level >= DEBUG; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/Main.java b/langtools/src/share/classes/com/sun/tools/sjavac/Main.java new file mode 100644 index 00000000000..18aef109754 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/Main.java @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import com.sun.tools.sjavac.server.JavacServer; +import java.io.IOException; +import java.io.PrintStream; +import java.util.*; + +/** + * The main class of the smart javac wrapper tool. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class Main { + + /* This is a smart javac wrapper primarily used when building the OpenJDK, + though other projects are welcome to use it too. But please be aware + that it is not an official api and will change in the future. + (We really mean it!) + + Goals: + + ** Create a state file, containing information about the build, so + that incremental builds only rebuild what is necessary. Also the + state file can be used by make/ant to detect when to trigger + a call to the smart javac wrapper. + + This file is called bin/javac_state (assuming that you specified "-d bin") + Thus the simplest makefile is: + + SJAVAC=java -cp .../tools.jar com.sun.tools.sjavac.Main + SRCS=$(shell find src -name "*.java") + bin/javac_state : $(SRCS) + $(SJAVAC) src -d bin + + This makefile will run very fast and detect properly when Java code needs to + be recompiled. The smart javac wrapper will then use the information in java_state + to do an efficient incremental compile. + + Previously it was near enough impossible to write an efficient makefile for Java + with support for incremental builds and dependency tracking. + + ** Separate java sources to be compiled from java + sources used >only< for linking. The options: + + "dir" points to root dir with sources to be compiled + "-sourcepath dir" points to root dir with sources used only for linking + "-classpath dir" points to dir with classes used only for linking (as before) + + ** Use all cores for compilation by default. + "-j 4" limit the number of cores to 4. + For the moment, the sjavac server additionally limits the number of cores to three. + This will improve in the future when more sharing is performed between concurrent JavaCompilers. + + ** Basic translation support from other sources to java, and then compilation of the generated java. + This functionality might be moved into annotation processors instead. + Again this is driven by the OpenJDK sources where properties and a few other types of files + are converted into Java sources regularily. The javac_state embraces copy and tr, and perform + incremental recompiles and copying for these as well. META-INF will be a special copy rule + that will copy any files found below any META-INF dir in src to the bin/META-INF dir. + "-copy .gif" + "-copy META-INF" + "-tr .prop=com.sun.tools.javac.smart.CompileProperties + "-tr .propp=com.sun.tools.javac.smart.CompileProperties,java.util.ListResourceBundle + "-tr .proppp=com.sun.tools.javac.smart.CompileProperties,sun.util.resources.LocaleNamesBundle + + ** Control which classes in the src,sourcepath and classpath that javac is allowed to see. + Again, this is necessary to deal with the source code structure of the OpenJDK which is + intricate (read messy). + + "-i tools.*" to include the tools package and all its subpackages in the build. + "-x tools.net.aviancarrier.*" to exclude the aviancarrier package and all its sources and subpackages. + "-x tools.net.drums" to exclude the drums package only, keep its subpackages. + "-xf tools/net/Bar.java" // Do not compile this file... + "-xf *Bor.java" // Do not compile Bor.java wherever it is found, BUT do compile ABor.java! + "-if tools/net/Bor.java" // Only compile this file...odd, but sometimes used. + + ** The smart javac wrapper is driven by the modification time on the source files and compared + to the modification times written into the javac_state file. + + It does not compare the modification time of the source with the modification time of the artifact. + However it will detect if the modification time of an artifact has changed compared to the java_state, + and this will trigger a delete of the artifact and a subsequent recompile of the source. + + The smart javac wrapper is not a generic makefile/ant system. Its purpose is to compile java source + as the final step before the output dir is finalized and immediately jared, or jmodded. The output + dir should be considered opaque. Do not write into the outputdir yourself! + Any artifacts found in the outputdir that javac_state does not know of, will be deleted! + This can however be prevented, using the switch --permit-unidentified-artifacts + This switch is necessary when build the OpenJDK because its makefiles still write directly to + the output classes dirs. + + Any makefile/ant rules that want to put contents into the outputdir should put the content + in one of several source roots. Static content that is under version control, can be put in the same source + code tree as the Java sources. Dynamic content that is generated by make/ant on the fly, should + be put in a separate gensrc_stuff root. The smart javac wrapper call will then take the arguments: + "gensrc_stuff src -d bin" + + The command line: + java -cp tools.jar com.sun.tools.sjavac.Main \ + -i "com.bar.*" -x "com.bar.foo.*" \ + first_root \ + -i "com.bar.foo.*" \ + second_root \ + -x "org.net.*" \ + -sourcepath link_root_sources \ + -classpath link_root_classes \ + -d bin + + Will compile all sources for package com.bar and its subpackages, found below first_root, + except the package com.bar.foo (and its subpackages), for which the sources are picked + from second_root instead. It will link against classes in link_root_classes and against + sources in link_root_sources, but will not see (try to link against) sources matching org.net.* + but will link against org.net* classes (if they exist) in link_root_classes. + + (If you want a set of complex filter rules to be applied to several source directories, without + having to repeat the the filter rules for each root. You can use the explicit -src option. For example: + sjavac -x "com.foo.*" -src root1:root2:root3 ) + + The resulting classes are written into bin. + */ + + // This is the final destination for classes and copied files. + private File bin_dir; + // This is where the annotation process will put generated sources. + private File gensrc_dir; + // This is where javac -h puts the generated c-header files. + private File header_dir; + + // This file contains the list of sources genereated by the makefile. + // We double check that our calculated list of sources matches this list, + // if not, then we terminate with an error! + private File makefile_source_list; + // The challenging task to manage an incremental build is done by javac_state. + private JavacState javac_state; + + // The suffix rules tells you for example, that .java files should be compiled, + // and .html files should be copied and .properties files be translated. + Map suffix_rules; + + public static void main(String... args) { + if (args.length > 0 && args[0].startsWith("--startserver:")) { + if (args.length>1) { + Log.error("When spawning a background server, only a single --startserver argument is allowed."); + return; + } + // Spawn a background server. + int rc = JavacServer.startServer(args[0], System.err); + System.exit(rc); + } + Main main = new Main(); + int rc = main.go(args, System.out, System.err); + // Remove the portfile, but only if this background=false was used. + JavacServer.cleanup(args); + System.exit(rc); + } + + private void printHelp() { + System.out.println("Usage: sjavac \n"+ + "where required options are:\n"+ + "dir Compile all sources in dir recursively\n"+ + "-d dir Store generated classes here and the javac_state file\n"+ + "--server:portfile=/tmp/abc Use a background sjavac server\n\n"+ + "All other arguments as javac, except -implicit:none which is forced by default.\n"+ + "No java source files can be supplied on the command line, nor can an @file be supplied.\n\n"+ + "Warning!\n"+ + "This tool might disappear at any time, and its command line options might change at any time!"); + } + + public int go(String[] args, PrintStream out, PrintStream err) { + try { + if (args.length == 0 || findJavaSourceFiles(args) || findAtFile(args) || null==Util.findServerSettings(args)) { + printHelp(); + return 0; + } + + Log.setLogLevel(findLogLevel(args), out, err); + String server_settings = Util.findServerSettings(args); + args = verifyImplicitOption(args); + // Find the source root directories, and add the -src option before these, if not there already. + args = addSrcBeforeDirectories(args); + // Check that there is at least one -src supplied. + checkSrcOption(args); + // Check that there is one -d supplied. + bin_dir = findDirectoryOption(args,"-d","output", true, false, true); + gensrc_dir = findDirectoryOption(args,"-s","gensrc", false, false, true); + header_dir = findDirectoryOption(args,"-h","headers", false, false, true); + makefile_source_list = findFileOption(args,"--compare-found-sources","makefile source list", false); + + // Load the prev build state database. + javac_state = JavacState.load(args, bin_dir, gensrc_dir, header_dir, + findBooleanOption(args, "--permit-unidentified-artifacts"), out, err); + + // Setup the suffix rules from the command line. + suffix_rules = javac_state.getJavaSuffixRule(); + findTranslateOptions(args, suffix_rules); + if (suffix_rules.keySet().size() > 1 && gensrc_dir == null) { + Log.error("You have translators but no gensrc dir (-s) specified!"); + return -1; + } + findCopyOptions(args, suffix_rules); + + // All found modules are put here. + Map modules = new HashMap(); + // We start out in the legacy empty no-name module. + // As soon as we stumble on a module-info.java file we change to that module. + Module current_module = new Module("", ""); + modules.put("", current_module); + + // Find all sources, use the suffix rules to know which files are sources. + Map sources = new HashMap(); + // Find the files, this will automatically populate the found modules + // with found packages where the sources are found! + findFiles(args, "-src", suffix_rules.keySet(), sources, modules, current_module, false); + + if (sources.isEmpty()) { + Log.error("Found nothing to compile!"); + return -1; + } + + // Find all source files allowable for linking. + // We might find more modules here as well. + Map sources_to_link_to = new HashMap(); + // Always reuse -src for linking as well! This means that we might + // get two -sourcepath on the commandline after the rewrite, which is + // fine. We can have as many as we like. You need to have separate -src/-sourcepath/-classpath + // if you need different filtering rules for different roots. If you have the same filtering + // rules for all sourcepath roots, you can concatenate them using :(;) as before. + rewriteOptions(args, "-src", "-sourcepath"); + findFiles(args, "-sourcepath", Util.set(".java"), sources_to_link_to, modules, current_module, true); + + // Find all class files allowable for linking. + // And pickup knowledge of all modules found here. + // This cannot currently filter classes inside jar files. + Map classes_to_link_to = new HashMap(); +// findFiles(args, "-classpath", Util.set(".class"), classes_to_link_to, modules, current_module, true); + + // Find all module sources allowable for linking. + Map modules_to_link_to = new HashMap(); + // findFiles(args, "-modulepath", Util.set(".class"), modules_to_link_to, modules, current_module, true); + + // Add the set of sources to the build database. + javac_state.now().collectPackagesSourcesAndArtifacts(modules); + javac_state.now().checkInternalState("checking sources", false, sources); + javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to); + javac_state.setVisibleSources(sources_to_link_to); + + // If there is any change in the source files, taint packages + // and mark the database in need of saving. + javac_state.checkSourceStatus(false); + + // Find all existing artifacts. Their timestamp will match the last modified timestamps stored + // in javac_state, simply because loading of the JavacState will clean out all artifacts + // that do not match the javac_state database. + javac_state.findAllArtifacts(); + + // Remove unidentified artifacts from the bin, gensrc and header dirs. + // (Unless we allow them to be there.) + // I.e. artifacts that are not known according to the build database (javac_state). + // For examples, files that have been manually copied into these dirs. + // Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp + // in javac_state) have already been removed when the javac_state was loaded. + if (!findBooleanOption(args, "--permit-unidentified-artifacts")) { + javac_state.removeUnidentifiedArtifacts(); + } + // Go through all sources and taint all packages that miss artifacts. + javac_state.taintPackagesThatMissArtifacts(); + + // Now clean out all known artifacts belonging to tainted packages. + javac_state.deleteClassArtifactsInTaintedPackages(); + // Copy files, for example property files, images files, xml files etc etc. + javac_state.performCopying(bin_dir, suffix_rules); + // Translate files, for example compile properties or compile idls. + javac_state.performTranslation(gensrc_dir, suffix_rules); + // Add any potentially generated java sources to the tobe compiled list. + // (Generated sources must always have a package.) + Map generated_sources = new HashMap(); + Source.scanRoot(gensrc_dir, Util.set(".java"), null, null, null, null, + generated_sources, modules, current_module, false, true, false); + javac_state.now().collectPackagesSourcesAndArtifacts(modules); + // Recheck the the source files and their timestamps again. + javac_state.checkSourceStatus(true); + + // Now do a safety check that the list of source files is identical + // to the list Make believes we are compiling. If we do not get this + // right, then incremental builds will fail with subtility. + // If any difference is detected, then we will fail hard here. + // This is an important safety net. + javac_state.compareWithMakefileList(makefile_source_list); + + // Do the compilations, repeatedly until no tainted packages exist. + boolean again; + // Collect the name of all compiled packages. + Set recently_compiled = new HashSet(); + boolean[] rc = new boolean[1]; + do { + // Clean out artifacts in tainted packages. + javac_state.deleteClassArtifactsInTaintedPackages(); + again = javac_state.performJavaCompilations(bin_dir, server_settings, args, recently_compiled, rc); + if (!rc[0]) break; + } while (again); + // Only update the state if the compile went well. + if (rc[0]) { + javac_state.save(); + // Collect all the artifacts. + javac_state.now().collectArtifacts(modules); + // Remove artifacts that were generated during the last compile, but not this one. + javac_state.removeSuperfluousArtifacts(recently_compiled); + } + return rc[0] ? 0 : -1; + } catch (ProblemException e) { + Log.error(e.getMessage()); + return -1; + } catch (Exception e) { + e.printStackTrace(err); + return -1; + } + } + + /** + * Are java source files passed on the command line? + */ + private boolean findJavaSourceFiles(String[] args) { + String prev = ""; + for (String s : args) { + if (s.endsWith(".java") && !prev.equals("-xf") && !prev.equals("-if")) { + return true; + } + prev = s; + } + return false; + } + + /** + * Is an at file passed on the command line? + */ + private boolean findAtFile(String[] args) { + for (String s : args) { + if (s.startsWith("@")) { + return true; + } + } + return false; + } + + /** + * Find the log level setting. + */ + private String findLogLevel(String[] args) { + for (String s : args) { + if (s.startsWith("--log=") && s.length()>6) { + return s.substring(6); + } + if (s.equals("-verbose")) { + return "info"; + } + } + return "info"; + } + + /** + * Remove smart javac wrapper arguments, before feeding + * the args to the plain javac. + */ + static String[] removeWrapperArgs(String[] args) { + String[] out = new String[args.length]; + // The first source path index is remembered + // here. So that all following can be concatenated to it. + int source_path = -1; + // The same for class path. + int class_path = -1; + // And module path. + int module_path = -1; + int j = 0; + for (int i = 0; i= args.length) { + throw new ProblemException("You have to specify a directory following "+option+"."); + } + if (args[i+1].indexOf(File.pathSeparatorChar) != -1) { + throw new ProblemException("You must only specify a single directory for "+option+"."); + } + dir = new File(args[i+1]); + if (!dir.exists()) { + if (!create) { + throw new ProblemException("This directory does not exist: "+dir.getPath()); + } else + if (!makeSureExists(dir)) { + throw new ProblemException("Cannot create directory "+dir.getPath()); + } + } + if (!dir.isDirectory()) { + throw new ProblemException("\""+args[i+1]+"\" is not a directory."); + } + } + } + if (dir == null && needed) { + throw new ProblemException("You have to specify "+option); + } + try { + if (dir != null) + return dir.getCanonicalFile(); + } catch (IOException e) { + throw new ProblemException(""+e); + } + return null; + } + + /** + * Option is followed by path. + */ + private static boolean shouldBeFollowedByPath(String o) { + return o.equals("-s") || + o.equals("-h") || + o.equals("-d") || + o.equals("-sourcepath") || + o.equals("-classpath") || + o.equals("-bootclasspath") || + o.equals("-src"); + } + + /** + * Add -src before source root directories if not already there. + */ + private static String[] addSrcBeforeDirectories(String[] args) { + List newargs = new ArrayList(); + for (int i = 0; i dirs = new HashSet(); + for (int i = 0; i= args.length) { + throw new ProblemException("You have to specify a directory following -src."); + } + StringTokenizer st = new StringTokenizer(args[i+1], File.pathSeparator); + while (st.hasMoreElements()) { + File dir = new File(st.nextToken()); + if (!dir.exists()) { + throw new ProblemException("This directory does not exist: "+dir.getPath()); + } + if (!dir.isDirectory()) { + throw new ProblemException("\""+dir.getPath()+"\" is not a directory."); + } + if (dirs.contains(dir)) { + throw new ProblemException("The src directory \""+dir.getPath()+"\" is specified more than once!"); + } + dirs.add(dir); + } + } + } + if (dirs.isEmpty()) { + throw new ProblemException("You have to specify -src."); + } + } + + /** + * Scan the arguments to find an option that specifies a file. + */ + private static File findFileOption(String[] args, String option, String name, boolean needed) + throws ProblemException, ProblemException { + File file = null; + for (int i = 0; i= args.length) { + throw new ProblemException("You have to specify a file following "+option+"."); + } + file = new File(args[i+1]); + if (file.isDirectory()) { + throw new ProblemException("\""+args[i+1]+"\" is not a file."); + } + if (!file.exists() && needed) { + throw new ProblemException("The file \""+args[i+1]+"\" does not exist."); + } + + } + } + if (file == null && needed) { + throw new ProblemException("You have to specify "+option); + } + return file; + } + + /** + * Look for a specific switch, return true if found. + */ + public static boolean findBooleanOption(String[] args, String option) { + for (int i = 0; i i+1) { + rc = Integer.parseInt(args[i+1]); + } + } + } + return rc; + } + + /** + * Scan the arguments to find the option (-tr) that setup translation rules to java source + * from different sources. For example: .properties are translated using CompileProperties + * The found translators are stored as suffix rules. + */ + private static void findTranslateOptions(String[] args, Map suffix_rules) + throws ProblemException, ProblemException { + + for (int i = 0; i= args.length) { + throw new ProblemException("You have to specify a translate rule following -tr."); + } + String s = args[i+1]; + checkTranslatePattern(s); + int ep = s.indexOf("="); + String suffix = s.substring(0,ep); + String classname = s.substring(ep+1); + if (suffix_rules.get(suffix) != null) { + throw new ProblemException("You have already specified a "+ + "rule for the suffix "+suffix); + } + if (s.equals(".class")) { + throw new ProblemException("You cannot have a translator for .class files!"); + } + if (s.equals(".java")) { + throw new ProblemException("You cannot have a translator for .java files!"); + } + String extra = null; + int exp = classname.indexOf(","); + if (exp != -1) { + extra = classname.substring(exp+1); + classname = classname.substring(0,exp); + } + try { + Class cl = Class.forName(classname); + Transformer t = (Transformer)cl.newInstance(); + t.setExtra(extra); + suffix_rules.put(suffix, t); + } + catch (Exception e) { + throw new ProblemException("Cannot use "+classname+" as a translator!"); + } + } + } + } + + /** + * Scan the arguments to find the option (-copy) that setup copying rules into the bin dir. + * For example: -copy .html + * The found copiers are stored as suffix rules as well. No translation is done, just copying. + */ + private void findCopyOptions(String[] args, Map suffix_rules) + throws ProblemException, ProblemException { + + for (int i = 0; i= args.length) { + throw new ProblemException("You have to specify a translate rule following -tr."); + } + String s = args[i+1]; + checkCopyPattern(s); + if (suffix_rules.get(s) != null) { + throw new ProblemException("You have already specified a "+ + "rule for the suffix "+s); + } + if (s.equals(".class")) { + throw new ProblemException("You cannot have a copy rule for .class files!"); + } + if (s.equals(".java")) { + throw new ProblemException("You cannot have a copy rule for .java files!"); + } + suffix_rules.put(s, javac_state.getCopier()); + } + } + } + + /** + * Rewrite a / separated path into \ separated, but only + * if we are running on a platform were File.separatorChar=='\', ie winapi. + */ + private String fixupSeparator(String p) { + if (File.separatorChar == '/') return p; + return p.replaceAll("/", "\\\\"); + } + + /** + * Scan the arguments for -i -x -xf -if followed by the option + * -src, -sourcepath, -modulepath or -classpath and produce a map of all the + * files to referenced for that particular option. + * + * Store the found sources and the found modules in the supplied maps. + */ + private boolean findFiles(String[] args, String option, Set suffixes, + Map found_files, Map found_modules, + Module current_module, boolean inLinksrc) + throws ProblemException, ProblemException + { + // Track which source roots, source path roots and class path roots have been added. + Set roots = new HashSet(); + // Track the current set of package includes,excludes as well as excluded source files, + // to be used in the next -src/-sourcepath/-classpath + List includes = new LinkedList(); + List excludes = new LinkedList(); + List excludefiles = new LinkedList(); + List includefiles = new LinkedList(); + // This include is used to find all modules in the source. + List moduleinfo = new LinkedList(); + moduleinfo.add("module-info.java"); + + for (int i = 0; i= args.length) { + throw new ProblemException("You have to specify a package pattern following -i"); + } + String incl = args[i+1]; + checkPattern(incl); + includes.add(incl); + } + if (args[i].equals("-x")) { + if (i+1 >= args.length) { + throw new ProblemException("You have to specify a package pattern following -x"); + } + String excl = args[i+1]; + checkPattern(excl); + excludes.add(excl); + } + if (args[i].equals("-xf")) { + if (i+1 >= args.length) { + throw new ProblemException("You have to specify a file following -xf"); + } + String exclf = args[i+1]; + checkFilePattern(exclf); + exclf = Util.normalizeDriveLetter(exclf); + excludefiles.add(fixupSeparator(exclf)); + } + if (args[i].equals("-if")) { + if (i+1 >= args.length) { + throw new ProblemException("You have to specify a file following -xf"); + } + String inclf = args[i+1]; + checkFilePattern(inclf); + inclf = Util.normalizeDriveLetter(inclf); + includefiles.add(fixupSeparator(inclf)); + } + if (args[i].equals(option)) { + if (i+1 >= args.length) { + throw new ProblemException("You have to specify a directory following "+option); + } + String[] root_dirs = args[i+1].split(File.pathSeparator); + for (String r : root_dirs) { + File root = new File(r); + if (!root.isDirectory()) { + throw new ProblemException("\""+r+"\" is not a directory."); + } + try { + root = root.getCanonicalFile(); + } catch (IOException e) { + throw new ProblemException(""+e); + } + if (roots.contains(root)) { + throw new ProblemException("\""+r+"\" has already been used for "+option); + } + if (roots.equals(bin_dir)) { + throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -d"); + } + if (roots.equals(gensrc_dir)) { + throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -s"); + } + if (roots.equals(header_dir)) { + throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -h"); + } + roots.add(root); + Source.scanRoot(root, suffixes, excludes, includes, excludefiles, includefiles, + found_files, found_modules, current_module, + findBooleanOption(args, "--permit-sources-without-package"), + false, inLinksrc); + } + } + if (args[i].equals("-src") || + args[i].equals("-sourcepath") || + args[i].equals("-modulepath") || + args[i].equals("-classpath")) + { + // Reset the includes,excludes and excludefiles after they have been used. + includes = new LinkedList(); + excludes = new LinkedList(); + excludefiles = new LinkedList(); + includefiles = new LinkedList(); + } + } + return true; + } + +} + diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/Module.java b/langtools/src/share/classes/com/sun/tools/sjavac/Module.java new file mode 100644 index 00000000000..db84a405deb --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/Module.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.File; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The module is the root of a set of packages/sources/artifacts. + * At the moment there is only one module in use, the empty/no-name/default module. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class Module implements Comparable { + private String name; + private String dirname; + private Map packages = new HashMap(); + private Map sources = new HashMap(); + private Map artifacts = new HashMap(); + + public Module(String n, String dn) { + name = n; + dirname = n; + } + + public String name() { return name; } + public String dirname() { return dirname; } + public Map packages() { return packages; } + public Map sources() { return sources; } + public Map artifacts() { return artifacts; } + + @Override + public boolean equals(Object o) { + return (o instanceof Module) && name.equals(((Module)o).name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public int compareTo(Module o) { + return name.compareTo(o.name); + } + + public void save(StringBuilder b) { + b.append("M ").append(name).append(":").append("\n"); + Package.savePackages(packages, b); + } + + public static Module load(String l) { + int cp = l.indexOf(':',2); + if (cp == -1) return null; + String name = l.substring(2,cp); + return new Module(name, ""); + } + + public static void saveModules(Map ms, StringBuilder b) + { + for (Module m : ms.values()) { + m.save(b); + } + } + + public void addPackage(Package p) { + packages.put(p.name(), p); + } + + public Package lookupPackage(String pkg) { + Package p = packages.get(pkg); + if (p == null) { + p = new Package(this, pkg); + packages.put(pkg, p); + } + return p; + } + + public void addSource(String pkg, Source src) { + Package p = lookupPackage(pkg); + src.setPackage(p); + p.addSource(src); + sources.put(src.file().getPath(), src); + } + + public Source lookupSource(String path) { + return sources.get(path); + } + + public void addArtifacts(String pkg, Set as) { + Package p = lookupPackage(pkg); + for (URI u : as) { + p.addArtifact(new File(u)); + } + } + + public void setDependencies(String pkg, Set deps) { + Package p = lookupPackage(pkg); + p.setDependencies(deps); + } + + public void setPubapi(String pkg, List ps) { + Package p = lookupPackage(pkg); + p.setPubapi(ps); + } + + public boolean hasPubapiChanged(String pkg, List ps) { + Package p = lookupPackage(pkg); + return p.hasPubapiChanged(ps); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/Package.java b/langtools/src/share/classes/com/sun/tools/sjavac/Package.java new file mode 100644 index 00000000000..93054852c4c --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/Package.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The Package class maintains meta information about a package. + * For example its sources, dependents,its pubapi and its artifacts. + * + * It might look odd that we track dependents/pubapi/artifacts on + * a package level, but it makes sense since recompiling a full package + * takes as long as recompiling a single java file in that package, + * if you take into account the startup time of the jvm. + * + * Also the dependency information will be much smaller (good for the javac_state file size) + * and it simplifies tracking artifact generation, you do not always know from which + * source a class file was generated, but you always know which package it belongs to. + * + * It is also educational to see package dependencies triggering recompilation of + * other packages. Even though the recompilation was perhaps not necessary, + * the visible recompilation of the dependent packages indicates how much circular + * dependencies your code has. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class Package implements Comparable { + // The module this package belongs to. (There is a legacy module with an empty string name, + // used for all legacy sources.) + private Module mod; + // Name of this package, module:pkg + // ex1 jdk.base:java.lang + // ex2 :java.lang (when in legacy mode) + private String name; + // The directory path to the package. If the package belongs to a module, + // then that module's file system name is part of the path. + private String dirname; + // This package depends on these packages. + private Set dependencies = new HashSet(); + // This package has the following dependents, that depend on this package. + private Set dependents = new HashSet(); + // This is the public api of this package. + private List pubapi = new ArrayList(); + // Map from source file name to Source info object. + private Map sources = new HashMap(); + // This package generated these artifacts. + private Map artifacts = new HashMap(); + + public Package(Module m, String n) { + int c = n.indexOf(":"); + assert(c != -1); + String mn = n.substring(0,c); + assert(m.name().equals(m.name())); + name = n; + dirname = n.replace('.', File.separatorChar); + if (m.name().length() > 0) { + // There is a module here, prefix the module dir name to the path. + dirname = m.dirname()+File.separatorChar+dirname; + } + } + + public Module mod() { return mod; } + public String name() { return name; } + public String dirname() { return dirname; } + public Map sources() { return sources; } + public Map artifacts() { return artifacts; } + public List pubapi() { return pubapi; } + + public Set dependencies() { return dependencies; } + public Set dependents() { return dependents; } + + @Override + public boolean equals(Object o) { + return (o instanceof Package) && name.equals(((Package)o).name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public int compareTo(Package o) { + return name.compareTo(o.name); + } + + public void addSource(Source s) { + sources.put(s.file().getPath(), s); + } + + public void addDependency(String d) { + dependencies.add(d); + } + + public void addDependent(String d) { + dependents.add(d); + } + + public void addPubapi(String p) { + pubapi.add(p); + } + + /** + * Check if we have knowledge in the javac state that + * describe the results of compiling this package before. + */ + public boolean existsInJavacState() { + return artifacts.size() > 0 || pubapi.size() > 0; + } + + public static List pubapiToList(String ps) + { + String[] lines = ps.split("\n"); + List r = new ArrayList(); + for (String l : lines) { + r.add(l); + } + return r; + } + + public boolean hasPubapiChanged(List ps) { + Iterator i = ps.iterator(); + Iterator j = pubapi.iterator(); + int line = 0; + while (i.hasNext() && j.hasNext()) { + String is = i.next(); + String js = j.next(); + if (!is.equals(js)) { + Log.debug("Change in pubapi for package "+name+" line "+line); + Log.debug("Old: "+js); + Log.debug("New: "+is); + return true; + } + line++; + } + if ((i.hasNext() && !j.hasNext() ) || + (!i.hasNext() && j.hasNext())) { + Log.debug("Change in pubapi for package "+name); + if (i.hasNext()) { + Log.debug("New has more lines!"); + } else { + Log.debug("Old has more lines!"); + } + return true; + } + return false; + } + + public void setPubapi(List ps) { + pubapi = ps; + } + + public void setDependencies(Set ds) { + dependencies = ds; + } + + public void save(StringBuilder b) { + b.append("P ").append(name).append("\n"); + Source.saveSources(sources, b); + saveDependencies(b); + savePubapi(b); + saveArtifacts(b); + } + + static public Package load(Module module, String l) { + String name = l.substring(2); + return new Package(module, name); + } + + public void loadDependency(String l) { + String n = l.substring(2); + addDependency(n); + } + + public void loadPubapi(String l) { + String pi = l.substring(2); + addPubapi(pi); + } + + public void saveDependencies(StringBuilder b) { + List sorted_dependencies = new ArrayList(); + for (String key : dependencies) { + sorted_dependencies.add(key); + } + Collections.sort(sorted_dependencies); + for (String a : sorted_dependencies) { + b.append("D "+a+"\n"); + } + } + + public void savePubapi(StringBuilder b) { + for (String l : pubapi) { + b.append("I "+l+"\n"); + } + } + + public static void savePackages(Map packages, StringBuilder b) { + List sorted_packages = new ArrayList(); + for (String key : packages.keySet() ) { + sorted_packages.add(key); + } + Collections.sort(sorted_packages); + for (String s : sorted_packages) { + Package p = packages.get(s); + p.save(b); + } + } + + public void addArtifact(String a) { + artifacts.put(a, new File(a)); + } + + public void addArtifact(File f) { + artifacts.put(f.getPath(), f); + } + + public void addArtifacts(Set as) { + for (URI u : as) { + addArtifact(new File(u)); + } + } + + public void setArtifacts(Set as) { + assert(!artifacts.isEmpty()); + artifacts = new HashMap(); + addArtifacts(as); + } + + public void loadArtifact(String l) { + // Find next space after "A ". + int dp = l.indexOf(' ',2); + String fn = l.substring(2,dp); + long last_modified = Long.parseLong(l.substring(dp+1)); + File f = new File(fn); + if (f.exists() && f.lastModified() != last_modified) { + // Hmm, the artifact on disk does not have the same last modified + // timestamp as the information from the build database. + // We no longer trust the artifact on disk. Delete it. + // The smart javac wrapper will then rebuild the artifact. + Log.debug("Removing "+f.getPath()+" since its timestamp does not match javac_state."); + f.delete(); + } + artifacts.put(f.getPath(), f); + } + + public void saveArtifacts(StringBuilder b) { + List sorted_artifacts = new ArrayList(); + for (File f : artifacts.values()) { + sorted_artifacts.add(f); + } + Collections.sort(sorted_artifacts); + for (File f : sorted_artifacts) { + // The last modified information is only used + // to detect tampering with the output dir. + // If the outputdir has been modified, not by javac, + // then a mismatch will be detected in the last modified + // timestamps stored in the build database compared + // to the timestamps on disk and the artifact will be deleted. + + b.append("A "+f.getPath()+" "+f.lastModified()+"\n"); + } + } + + /** + * Always clean out a tainted package before it is recompiled. + */ + public void deleteArtifacts() { + for (File a : artifacts.values()) { + a.delete(); + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/ProblemException.java b/langtools/src/share/classes/com/sun/tools/sjavac/ProblemException.java new file mode 100644 index 00000000000..53f7016190b --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/ProblemException.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +/** + * Used to signal serious problems when running sjavac. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class ProblemException extends Exception { + static final long serialVersionUID = -3387516993124229949L; + public ProblemException(String s) { + super(s); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/Source.java b/langtools/src/share/classes/com/sun/tools/sjavac/Source.java new file mode 100644 index 00000000000..927bbf11093 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/Source.java @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.File; +import java.util.Set; +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; + +/** A Source object maintains information about a source file. + * For example which package it belongs to and kind of source it is. + * The class also knows how to find source files (scanRoot) given include/exclude + * patterns and a root. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class Source implements Comparable { + // The package the source belongs to. + private Package pkg; + // Name of this source file, relative its source root. + // For example: java/lang/Object.java + // Or if the source file is inside a module: + // jdk.base/java/lang/Object.java + private String name; + // What kind of file is this. + private String suffix; + // When this source file was last_modified + private long lastModified; + // The source File. + private File file; + // The source root under which file resides. + private File root; + // If the source is generated. + private boolean isGenerated; + // If the source is only linked to, not compiled. + private boolean linkedOnly; + + @Override + public boolean equals(Object o) { + return (o instanceof Source) && name.equals(((Source)o).name); + } + + @Override + public int compareTo(Source o) { + return name.compareTo(o.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + public Source(Module m, String n, File f, File r) { + name = n; + int dp = n.lastIndexOf("."); + if (dp != -1) { + suffix = n.substring(dp); + } else { + suffix = ""; + } + file = f; + root = r; + lastModified = f.lastModified(); + linkedOnly = false; + } + + public Source(Package p, String n, long lm) { + pkg = p; + name = n; + int dp = n.lastIndexOf("."); + if (dp != -1) { + suffix = n.substring(dp); + } else { + suffix = ""; + } + file = null; + root = null; + lastModified = lm; + linkedOnly = false; + int ls = n.lastIndexOf('/'); + } + + public String name() { return name; } + public String suffix() { return suffix; } + public Package pkg() { return pkg; } + public File file() { return file; } + public File root() { return root; } + public long lastModified() { + return lastModified; + } + + public void setPackage(Package p) { + pkg = p; + } + + public void markAsGenerated() { + isGenerated = true; + } + + public boolean isGenerated() { + return isGenerated; + } + + public void markAsLinkedOnly() { + linkedOnly = true; + } + + public boolean isLinkedOnly() { + return linkedOnly; + } + + private void save(StringBuilder b) { + String CL = linkedOnly?"L":"C"; + String GS = isGenerated?"G":"S"; + b.append(GS+" "+CL+" "+name+" "+file.lastModified()+"\n"); + } + // Parse a line that looks like this: + // S C /code/alfa/A.java 1357631228000 + static public Source load(Package lastPackage, String l, boolean isGenerated) { + int sp = l.indexOf(' ',4); + if (sp == -1) return null; + String name = l.substring(4,sp); + long last_modified = Long.parseLong(l.substring(sp+1)); + + boolean isLinkedOnly = false; + if (l.charAt(2) == 'L') { + isLinkedOnly = true; + } else if (l.charAt(2) == 'C') { + isLinkedOnly = false; + } else return null; + + Source s = new Source(lastPackage, name, last_modified); + s.file = new File(name); + if (isGenerated) s.markAsGenerated(); + if (isLinkedOnly) s.markAsLinkedOnly(); + return s; + } + + public static void saveSources(Map sources, StringBuilder b) { + List sorted_sources = new ArrayList(); + for (String key : sources.keySet()) { + sorted_sources.add(key); + } + Collections.sort(sorted_sources); + for (String key : sorted_sources) { + Source s = sources.get(key); + s.save(b); + } + } + + /** + * Recurse into the directory root and find all files matchine the excl/incl/exclfiles/inclfiles rules. + * Detects the existence of module-info.java files and presumes that the directory it resides in + * is the name of the current module. + */ + static public void scanRoot(File root, + Set suffixes, + List excludes, List includes, + List excludeFiles, List includeFiles, + Map foundFiles, + Map foundModules, + Module currentModule, + boolean permitSourcesWithoutPackage, + boolean inGensrc, + boolean inLinksrc) + throws ProblemException { + + if (root == null) return; + int root_prefix = root.getPath().length()+1; + // This is the root source directory, it must not contain any Java sources files + // because we do not allow Java source files without a package. + // (Unless of course --permit-sources-without-package has been specified.) + // It might contain other source files however, (for -tr and -copy) these will + // always be included, since no package pattern can match the root directory. + currentModule = addFilesInDir(root, root_prefix, root, suffixes, permitSourcesWithoutPackage, + excludeFiles, includeFiles, false, + foundFiles, foundModules, currentModule, + inGensrc, inLinksrc); + + File[] dirfiles = root.listFiles(); + for (File d : dirfiles) { + if (d.isDirectory()) { + // Descend into the directory structure. + scanDirectory(d, root_prefix, root, suffixes, + excludes, includes, excludeFiles, includeFiles, + false, foundFiles, foundModules, currentModule, inGensrc, inLinksrc); + } + } + } + + /** + * Test if a path matches any of the patterns given. + * The pattern foo.bar matches only foo.bar + * The pattern foo.* matches foo.bar and foo.bar.zoo etc + */ + static private boolean hasMatch(String path, List patterns) { + for (String p : patterns) { + // Exact match + if (p.equals(path)) { + return true; + } + // Single dot the end matches this package and all its subpackages. + if (p.endsWith(".*")) { + // Remove the wildcard + String patprefix = p.substring(0,p.length()-2); + // Does the path start with the pattern prefix? + if (path.startsWith(patprefix)) { + // If the path has the same length as the pattern prefix, then it is a match. + // If the path is longer, then make sure that + // the next part of the path starts with a dot (.) to prevent + // wildcard matching in the middle of a package name. + if (path.length()==patprefix.length() || path.charAt(patprefix.length())=='.') { + return true; + } + } + } + } + return false; + } + + /** + * Matches patterns with the asterisk first. */ + // The pattern foo/bar.java only matches foo/bar.java + // The pattern */bar.java matches foo/bar.java and zoo/bar.java etc + static private boolean hasFileMatch(String path, List patterns) { + path = Util.normalizeDriveLetter(path); + for (String p : patterns) { + // Exact match + if (p.equals(path)) { + return true; + } + // Single dot the end matches this package and all its subpackages. + if (p.startsWith("*")) { + // Remove the wildcard + String patsuffix = p.substring(1); + // Does the path start with the pattern prefix? + if (path.endsWith(patsuffix)) { + return true; + } + } + } + return false; + } + + /** + * Add the files in the directory, assuming that the file has not been excluded. + * Returns a fresh Module object, if this was a dir with a module-info.java file. + */ + static private Module addFilesInDir(File dir, int rootPrefix, File root, + Set suffixes, boolean allow_javas, + List excludeFiles, List includeFiles, boolean all, + Map foundFiles, + Map foundModules, + Module currentModule, + boolean inGensrc, + boolean inLinksrc) + throws ProblemException + { + for (File f : dir.listFiles()) { + if (f.isFile()) { + boolean should_add = + (excludeFiles == null || excludeFiles.isEmpty() || !hasFileMatch(f.getPath(), excludeFiles)) + && (includeFiles == null || includeFiles.isEmpty() || hasFileMatch(f.getPath(), includeFiles)); + + if (should_add) { + if (!allow_javas && f.getName().endsWith(".java")) { + throw new ProblemException("No .java files are allowed in the source root "+dir.getPath()+ + ", please remove "+f.getName()); + } + // Extract the file name relative the root. + String fn = f.getPath().substring(rootPrefix); + // Extract the package name. + int sp = fn.lastIndexOf(File.separatorChar); + String pkg = ""; + if (sp != -1) { + pkg = fn.substring(0,sp).replace(File.separatorChar,'.'); + } + // Is this a module-info.java file? + if (fn.endsWith("module-info.java")) { + // Aha! We have recursed into a module! + if (!currentModule.name().equals("")) { + throw new ProblemException("You have an extra module-info.java inside a module! Please remove "+fn); + } + String module_name = fn.substring(0,fn.length()-16); + currentModule = new Module(module_name, f.getPath()); + foundModules.put(module_name, currentModule); + } + // Extract the suffix. + int dp = fn.lastIndexOf("."); + String suffix = ""; + if (dp > 0) { + suffix = fn.substring(dp); + } + // Should the file be added? + if (all || suffixes.contains(suffix)) { + Source of = foundFiles.get(f.getPath()); + if (of != null) { + throw new ProblemException("You have already added the file "+fn+" from "+of.file().getPath()); + } + of = currentModule.lookupSource(f.getPath()); + if (of != null) { + // Oups, the source is already added, could be ok, could be not, lets check. + if (inLinksrc) { + // So we are collecting sources for linking only. + if (of.isLinkedOnly()) { + // Ouch, this one is also for linking only. Bad. + throw new ProblemException("You have already added the link only file "+fn+" from "+of.file().getPath()); + } + // Ok, the existing source is to be compiled. Thus this link only is redundant + // since all compiled are also linked to. Continue to the next source. + // But we need to add the source, so that it will be visible to linking, + // if not the multi core compile will fail because a JavaCompiler cannot + // find the necessary dependencies for its part of the source. + foundFiles.put(f.getPath(), of); + continue; + } else { + // We are looking for sources to compile, if we find an existing to be compiled + // source with the same name, it is an internal error, since we must + // find the sources to be compiled before we find the sources to be linked to. + throw new ProblemException("Internal error: Double add of file "+fn+" from "+of.file().getPath()); + } + } + Source s = new Source(currentModule, f.getPath(), f, root); + if (inGensrc) s.markAsGenerated(); + if (inLinksrc) { + s.markAsLinkedOnly(); + } + pkg = currentModule.name()+":"+pkg; + foundFiles.put(f.getPath(), s); + currentModule.addSource(pkg, s); + } + } + } + } + return currentModule; + } + + private static boolean gurka = false; + + static private void scanDirectory(File dir, int rootPrefix, File root, + Set suffixes, + List excludes, List includes, + List excludeFiles, List includeFiles, boolean all, + Map foundFiles, + Map foundModules, + Module currentModule, boolean inGensrc, boolean inLinksrc) + throws ProblemException { + + String pkg_name = ""; + // Remove the root prefix from the dir path, and replace file separator with dots + // to get the package name. + if (dir.getPath().length() > rootPrefix) { + pkg_name = dir.getPath().substring(rootPrefix).replace(File.separatorChar,'.'); + } + // Should this package directory be included and not excluded? + if (all || ((includes==null || includes.isEmpty() || hasMatch(pkg_name, includes)) && + (excludes==null || excludes.isEmpty() || !hasMatch(pkg_name, excludes)))) { + // Add the source files. + currentModule = addFilesInDir(dir, rootPrefix, root, suffixes, true, excludeFiles, includeFiles, all, + foundFiles, foundModules, currentModule, inGensrc, inLinksrc); + } + + for (File d : dir.listFiles()) { + if (d.isDirectory()) { + // Descend into the directory structure. + scanDirectory(d, rootPrefix, root, suffixes, + excludes, includes, excludeFiles, includeFiles, all, + foundFiles, foundModules, currentModule, inGensrc, inLinksrc); + } + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/Transformer.java b/langtools/src/share/classes/com/sun/tools/sjavac/Transformer.java new file mode 100644 index 00000000000..4285cdc40bc --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/Transformer.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.PrintStream; +import java.net.URI; +import java.util.Set; +import java.util.Map; + +/** + * The transform interface is used to transform content inside a package, from one form to another. + * Usually the output form is an unpredictable number of output files. (eg class files) + * but can also be an unpredictable number of generated source files (eg idl2java) + * or a single predictable output file (eg when copying,cleaning or compiling a properties file). + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public interface Transformer +{ + /** + * The transform method takes a set of package names, mapped to their source files and to the + * pubapis of the packages. + * + * The transform implementation must: + * store the names of the generated artifacts for each package into package_artifacts + * store found dependencies to other packages into the supplied set package_dependencies + * store the public api for a package into the supplied set package_pubapis + * + * Any benign messages as a result of running the transform + * are written into stdout, and errors are written to stderr. + * + * The debug_level can be 0=silent (only warnings and errors) 1=normal 2=verbose 3 or greater=debug + * setExtra is used to set the extra information information that can be passed on + * the command line to the smart javac wrapper. + * + * If sjavac is building incrementally from an existing javac_state, the var incremental is true. + * + * The transformer will only be called if some source in the package (or dependency) has + * a modified timestamp. Thus the transformer might get called with many sources, of which + * only one has changed. The transformer is allowed to regenerate all artifacts but + * a better transformer will only write those artifacts that need updating. + * + * However the transformer must verify that the existing artifacts really are there! + * and it must always update package_artifacts, package_dependencies, and package_pubapis correctly. + * This means that at least for Java source, it will always have to recompile the sources. + * + * The transformer is allowed to put files anywhere in the dest_root. + * An example of this is, can be the META-INF transformer that copy files + * below META-INF directories to the single META-INF directory below dest_root. + * + * False is returned if there was an error that prevented the transform. + * I.e. something was printed on stderr. + * + * If num_cores is set to a non-zero value. The transform should attempt to use no more than these + * number of threads for heavy work. + */ + boolean transform(Map> pkgSrcs, + Set visibleSources, + Map> visibleClasses, + Map> oldPackageDependencies, + URI destRoot, + Map> packageArtifacts, + Map> packageDependencies, + Map packagePublicApis, + int debugLevel, + boolean incremental, + int numCores, + PrintStream out, + PrintStream err); + + void setExtra(String e); + void setExtra(String[] args); +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/Util.java b/langtools/src/share/classes/com/sun/tools/sjavac/Util.java new file mode 100644 index 00000000000..1570314c17c --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/Util.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.StringTokenizer; + +/** + * Utilities. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class Util { + + public static String toFileSystemPath(String pkgId) { + if (pkgId == null || pkgId.length()==0) return null; + String pn; + if (pkgId.charAt(0) == ':') { + // When the module is the default empty module. + // Do not prepend the module directory, because there is none. + // Thus :java.foo.bar translates to java/foo/bar (or \) + pn = pkgId.substring(1).replace('.',File.separatorChar); + } else { + // There is a module. Thus jdk.base:java.foo.bar translates + // into jdk.base/java/foo/bar + int cp = pkgId.indexOf(':'); + String mn = pkgId.substring(0,cp); + pn = mn+File.separatorChar+pkgId.substring(cp+1).replace('.',File.separatorChar); + } + return pn; + } + + public static String justPackageName(String pkgName) { + int c = pkgName.indexOf(":"); + assert(c != -1); + return pkgName.substring(c+1); + } + + public static String extractStringOption(String opName, String s) { + int p = s.indexOf(opName+"="); + if (p == -1) return null; + p+=opName.length()+1; + int pe = s.indexOf(',', p); + if (pe == -1) pe = s.length(); + return s.substring(p, pe); + } + + public static int extractIntOption(String opName, String s) { + int p = s.indexOf(opName+"="); + if (p == -1) return 0; + p+=opName.length()+1; + int pe = s.indexOf(',', p); + if (pe == -1) pe = s.length(); + int v = 0; + try { + v = Integer.parseInt(s.substring(p, pe)); + } catch (Exception e) {} + return v; + } + + /** + * Clean out unwanted sub options supplied inside a primary option. + * For example to only had portfile remaining from: + * settings="--server:id=foo,portfile=bar" + * do settings = cleanOptions("--server:",Util.set("-portfile"),settings); + * now settings equals "--server:portfile=bar" + * + * @param optionPrefix The option name, including colon, eg --server: + * @param allowsSubOptions A set of the allowed sub options, id portfile etc. + * @param s The option settings string. + */ + public static String cleanSubOptions(String optionPrefix, Set allowedSubOptions, String s) { + StringBuilder sb = new StringBuilder(); + if (!s.startsWith(optionPrefix)) return ""; + StringTokenizer st = new StringTokenizer(s.substring(optionPrefix.length()), ","); + while (st.hasMoreTokens()) { + String o = st.nextToken(); + int p = o.indexOf('='); + if (p>0) { + String key = o.substring(0,p); + String val = o.substring(p+1); + if (allowedSubOptions.contains(key)) { + if (sb.length() > 0) sb.append(','); + sb.append(key+"="+val); + } + } + } + return sb.toString(); + } + + /** + * Convenience method to create a set with strings. + */ + public static Set set(String... ss) { + Set set = new HashSet(); + set.addAll(Arrays.asList(ss)); + return set; + } + + /** + * Normalize windows drive letter paths to upper case to enable string + * comparison. + * + * @param file File name to normalize + * @return The normalized string if file has a drive letter at the beginning, + * otherwise the original string. + */ + public static String normalizeDriveLetter(String file) { + if (file.length() > 2 && file.charAt(1) == ':') { + return Character.toUpperCase(file.charAt(0)) + file.substring(1); + } else if (file.length() > 3 && file.charAt(0) == '*' + && file.charAt(2) == ':') { + // Handle a wildcard * at the beginning of the string. + return file.substring(0, 1) + Character.toUpperCase(file.charAt(1)) + + file.substring(2); + } + return file; + } + + /** + * Locate the setting for the server properties. + */ + public static String findServerSettings(String[] args) { + for (String s : args) { + if (s.startsWith("--server:")) { + return s; + } + } + return null; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/comp/Dependencies.java b/langtools/src/share/classes/com/sun/tools/sjavac/comp/Dependencies.java new file mode 100644 index 00000000000..8f1930c8954 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/comp/Dependencies.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.comp; + +import javax.lang.model.element.Element; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Name; + +/** Utility class containing dependency information between packages + * and the pubapi for a package. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class Dependencies { + protected static final Context.Key dependenciesKey = + new Context.Key(); + + // The log to be used for error reporting. + protected Log log; + // Map from package name to packages that the package depends upon. + protected Map> deps; + // This is the set of all packages that are supplied + // through the java files at the command line. + protected Set explicitPackages; + + // Map from a package name to its public api. + // Will the Name encode the module in the future? + // If not, this will have to change to map from Module+Name to public api. + protected Map publicApiPerClass; + + public static Dependencies instance(Context context) { + Dependencies instance = context.get(dependenciesKey); + if (instance == null) + instance = new Dependencies(context); + return instance; + } + + private Dependencies(Context context) { + context.put(dependenciesKey, this); + log = Log.instance(context); + } + + public void reset() + { + deps = new HashMap>(); + explicitPackages = new HashSet(); + publicApiPerClass = new HashMap(); + } + + /** + * Fetch the set of dependencies that are relevant to the compile + * that has just been performed. I.e. we are only interested in + * dependencies for classes that were explicitly compiled. + * @return + */ + public Map> getDependencies() { + Map> new_deps = new HashMap>(); + if (explicitPackages == null) return new_deps; + for (Name pkg : explicitPackages) { + Set set = deps.get(pkg); + if (set != null) { + Set new_set = new_deps.get(pkg.toString()); + if (new_set == null) { + new_set = new HashSet(); + // Modules beware.... + new_deps.put(":"+pkg.toString(), new_set); + } + for (Name d : set) { + new_set.add(":"+d.toString()); + } + } + } + return new_deps; + } + + class CompareNames implements Comparator { + public int compare(Name a, Name b) { + return a.toString().compareTo(b.toString()); + } + + public boolean equals(Object obj) { + return super.equals(obj); + } + } + + /** + * Convert the map from class names to their pubapi to a map + * from package names to their pubapi (which is the sorted concatenation + * of all the class pubapis) + */ + public Map getPubapis() { + Map publicApiPerPackage = new HashMap(); + if (publicApiPerClass == null) return publicApiPerPackage; + Name[] keys = publicApiPerClass.keySet().toArray(new Name[0]); + Arrays.sort(keys, new CompareNames()); + StringBuffer newPublicApi = new StringBuffer(); + int i=0; + String prevPkg = ""; + for (Name k : keys) { + String cn = k.toString(); + String pn = ""; + int dp = cn.lastIndexOf('.'); + if (dp != -1) { + pn = cn.substring(0,dp); + } + if (!pn.equals(prevPkg)) { + if (!prevPkg.equals("")) { + // Add default module name ":" + publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString()); + } + newPublicApi = new StringBuffer(); + prevPkg = pn; + } + newPublicApi.append(publicApiPerClass.get(k)); + i++; + } + if (!prevPkg.equals("")) + publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString()); + return publicApiPerPackage; + } + + /** + * Visit the api of a class and construct a pubapi string and + * store it into the pubapi_perclass map. + */ + public void visitPubapi(Element e) { + Name n = ((ClassSymbol)e).fullname; + Name p = ((ClassSymbol)e).packge().fullname; + StringBuffer sb = publicApiPerClass.get(n); + assert(sb == null); + sb = new StringBuffer(); + PubapiVisitor v = new PubapiVisitor(sb); + v.visit(e); + if (sb.length()>0) { + publicApiPerClass.put(n, sb); + } + explicitPackages.add(p); + } + + /** + * Collect a dependency. curr_pkg is marked as depending on dep_pkg. + */ + public void collect(Name currPkg, Name depPkg) { + if (!currPkg.equals(depPkg)) { + Set theset = deps.get(currPkg); + if (theset==null) { + theset = new HashSet(); + deps.put(currPkg, theset); + } + theset.add(depPkg); + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java b/langtools/src/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java new file mode 100644 index 00000000000..d3dceeb2359 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.comp; + +import java.util.StringTokenizer; + +import com.sun.tools.javac.main.JavaCompiler; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.sjavac.server.CompilerThread; +import java.io.File; + +/** Subclass to Resolve that overrides collect. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class JavaCompilerWithDeps extends JavaCompiler { + + /** The dependency database + */ + protected Dependencies deps; + protected CompilerThread compilerThread; + + public JavaCompilerWithDeps(Context context, CompilerThread t) { + super(context); + deps = Dependencies.instance(context); + compilerThread = t; + needRootClasses = true; + } + + public static void preRegister(Context context, final CompilerThread t) { + context.put(compilerKey, new Context.Factory() { + public JavaCompiler make(Context c) { + JavaCompiler instance = new JavaCompilerWithDeps(c, t); + c.put(JavaCompiler.class, instance); + return instance; + } + }); + } + + /** Collect the public apis of classes supplied explicitly for compilation. + * @param sym The class to visit. + */ + @Override + public void reportPublicApi(ClassSymbol sym) { + // The next test will catch when source files are located in the wrong directory! + // This ought to be moved into javac as a new warning, or perhaps as part + // of the auxiliary class warning. + + // For example if sun.swing.BeanInfoUtils + // is in fact stored in: /mybuild/jdk/gensrc/javax/swing/beaninfo/BeanInfoUtils.java + + // We do not need to test that BeanInfoUtils is stored in a file named BeanInfoUtils + // since this is checked earlier. + if (sym.sourcefile != null) { + // Rewrite sun.swing.BeanInfoUtils into /sun/swing/ + StringBuilder pathb = new StringBuilder(); + StringTokenizer qn = new StringTokenizer(sym.packge().toString(), "."); + boolean first = true; + while (qn.hasMoreTokens()) { + String o = qn.nextToken(); + pathb.append("/"); + pathb.append(o); + first = false; + } + pathb.append("/"); + String path = pathb.toString(); + + // Now cut the uri to be: file:///mybuild/jdk/gensrc/javax/swing/beaninfo/ + String p = sym.sourcefile.toUri().getPath(); + // Do not use File.separatorChar here, a URI always uses slashes /. + int i = p.lastIndexOf("/"); + String pp = p.substring(0,i+1); + + // Now check if the truncated uri ends with the path. (It does not == failure!) + if (path.length() > 0 && !path.equals("/unnamed package/") && !pp.endsWith(path)) { + compilerThread.logError("Error: The source file "+sym.sourcefile.getName()+ + " is located in the wrong package directory, because it contains the class "+ + sym.getQualifiedName()); + } + } + deps.visitPubapi(sym); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java b/langtools/src/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java new file mode 100644 index 00000000000..0b5512dd2a7 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.comp; + +import java.util.Iterator; +import java.util.List; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementScanner6; + +/** Utility class that constructs a textual representation + * of the public api of a class. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class PubapiVisitor extends ElementScanner6 { + + StringBuffer sb; + // Important that it is 1! Part of protocol over wire, silly yes. + // Fix please. + int indent = 1; + + public PubapiVisitor(StringBuffer sb) { + this.sb = sb; + } + + String depth(int l) { + return " ".substring(0, l); + } + + @Override + public Void visitType(TypeElement e, Void p) { + if (e.getModifiers().contains(Modifier.PUBLIC) + || e.getModifiers().contains(Modifier.PROTECTED)) + { + sb.append(depth(indent) + "TYPE " + e.getQualifiedName() + "\n"); + indent += 2; + Void v = super.visitType(e, p); + indent -= 2; + return v; + } + return null; + } + + @Override + public Void visitVariable(VariableElement e, Void p) { + if (e.getModifiers().contains(Modifier.PUBLIC) + || e.getModifiers().contains(Modifier.PROTECTED)) { + sb.append(depth(indent)).append("VAR ") + .append(makeVariableString(e)).append("\n"); + } + // Safe to not recurse here, because the only thing + // to visit here is the constructor of a variable declaration. + // If it happens to contain an anonymous inner class (which it might) + // then this class is never visible outside of the package anyway, so + // we are allowed to ignore it here. + return null; + } + + @Override + public Void visitExecutable(ExecutableElement e, Void p) { + if (e.getModifiers().contains(Modifier.PUBLIC) + || e.getModifiers().contains(Modifier.PROTECTED)) { + sb.append(depth(indent)).append("METHOD ") + .append(makeMethodString(e)).append("\n"); + } + return null; + } + + /** + * Creates a String representation of a method element with everything + * necessary to track all public aspects of it in an API. + * @param e Element to create String for. + * @return String representation of element. + */ + protected String makeMethodString(ExecutableElement e) { + StringBuilder result = new StringBuilder(); + for (Modifier modifier : e.getModifiers()) { + result.append(modifier.toString()); + result.append(" "); + } + result.append(e.getReturnType().toString()); + result.append(" "); + result.append(e.toString()); + + List thrownTypes = e.getThrownTypes(); + if (!thrownTypes.isEmpty()) { + result.append(" throws "); + for (Iterator iterator = thrownTypes + .iterator(); iterator.hasNext();) { + TypeMirror typeMirror = iterator.next(); + result.append(typeMirror.toString()); + if (iterator.hasNext()) { + result.append(", "); + } + } + } + return result.toString(); + } + + /** + * Creates a String representation of a variable element with everything + * necessary to track all public aspects of it in an API. + * @param e Element to create String for. + * @return String representation of element. + */ + protected String makeVariableString(VariableElement e) { + StringBuilder result = new StringBuilder(); + for (Modifier modifier : e.getModifiers()) { + result.append(modifier.toString()); + result.append(" "); + } + result.append(e.asType().toString()); + result.append(" "); + result.append(e.toString()); + Object value = e.getConstantValue(); + if (value != null) { + result.append(" = "); + if (e.asType().toString().equals("char")) { + int v = (int)value.toString().charAt(0); + result.append("'\\u"+Integer.toString(v,16)+"'"); + } else { + result.append(value.toString()); + } + } + return result.toString(); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java b/langtools/src/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java new file mode 100644 index 00000000000..19c62e9e6f4 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.comp; + +import com.sun.tools.javac.comp.Resolve; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.code.Symbol; + +/** Subclass to Resolve that overrides collect. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class ResolveWithDeps extends Resolve { + + /** The dependency database + */ + protected Dependencies deps; + + protected ResolveWithDeps(Context context) { + super(context); + deps = Dependencies.instance(context); + } + + public static void preRegister(Context context) { + context.put(resolveKey, new Context.Factory() { + public Resolve make(Context c) { + Resolve instance = new ResolveWithDeps(c); + c.put(Resolve.class, instance); + return instance; + } + }); + } + /** Collect dependencies in the enclosing class + * @param from The enclosing class sym + * @param to The enclosing classes references this sym. + * */ + @Override + public void reportDependence(Symbol from, Symbol to) { + // Capture dependencies between the packages. + deps.collect(from.packge().fullname, to.packge().fullname); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java b/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java new file mode 100644 index 00000000000..eeaf9b03954 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.comp; + +import com.sun.tools.javac.util.ListBuffer; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URI; +import java.util.Set; +import java.util.HashSet; +import java.util.Map; +import java.util.HashMap; +import javax.tools.*; +import javax.tools.JavaFileObject.Kind; + +/** + * Intercepts reads and writes to the file system to gather + * information about what artifacts are generated. + * + * Traps writes to certain files, if the content written is identical + * to the existing file. + * + * Can also blind out the filemanager from seeing certain files in the file system. + * Necessary to prevent javac from seeing some sources where the source path points. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class SmartFileManager extends ForwardingJavaFileManager { + + // Set of sources that can be seen by javac. + Set visibleSources = new HashSet(); + // Map from modulename:packagename to artifacts. + Map> packageArtifacts = new HashMap>(); + // Where to print informational messages. + PrintWriter stdout; + + public SmartFileManager(JavaFileManager fileManager) { + super(fileManager); + } + + public void setVisibleSources(Set s) { + visibleSources = s; + } + + public void cleanArtifacts() { + packageArtifacts = new HashMap>(); + } + + public void setLog(PrintWriter pw) { + stdout = pw; + } + + public Map> getPackageArtifacts() { + return packageArtifacts; + } + + @Override + public Iterable list(Location location, + String packageName, + Set kinds, + boolean recurse) + throws IOException + { + // Acquire the list of files. + Iterable files = super.list(location, packageName, kinds, recurse); + if (visibleSources.isEmpty()) { + return files; + } + // Now filter! + ListBuffer filteredFiles = new ListBuffer(); + for (JavaFileObject f : files) { + URI uri = f.toUri(); + String t = uri.toString(); + if (t.startsWith("jar:") + || t.endsWith(".class") + || visibleSources.contains(uri)) + { + filteredFiles.add(f); + } + } + return filteredFiles; + } + + @Override + public boolean hasLocation(Location location) { + return super.hasLocation(location); + } + + @Override + public JavaFileObject getJavaFileForInput(Location location, + String className, + Kind kind) + throws IOException + { + JavaFileObject file = super.getJavaFileForInput(location, className, kind); + if (file == null || visibleSources.isEmpty()) { + return file; + } + + if (visibleSources.contains(file.toUri())) { + return file; + } + return null; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, + String className, + Kind kind, + FileObject sibling) + throws IOException + { + JavaFileObject file = super.getJavaFileForOutput(location, className, kind, sibling); + if (file == null) return file; + int dp = className.lastIndexOf('.'); + String pkg_name = ""; + if (dp != -1) { + pkg_name = className.substring(0, dp); + } + // When modules are in use, then the mod_name might be something like "jdk_base" + String mod_name = ""; + addArtifact(mod_name+":"+pkg_name, file.toUri()); + return file; + } + + @Override + public FileObject getFileForInput(Location location, + String packageName, + String relativeName) + throws IOException + { + FileObject file = super.getFileForInput(location, packageName, relativeName); + if (file == null || visibleSources.isEmpty()) { + return file; + } + + if (visibleSources.contains(file.toUri())) { + return file; + } + return null; + } + + @Override + public FileObject getFileForOutput(Location location, + String packageName, + String relativeName, + FileObject sibling) + throws IOException + { + FileObject file = super.getFileForOutput(location, packageName, relativeName, sibling); + if (file == null) return file; + if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && + file instanceof JavaFileObject) { + file = new SmartFileObject((JavaFileObject)file, stdout); + packageName = ":" + packageNameFromFileName(relativeName); + } + if (packageName.equals("")) { + packageName = ":"; + } + addArtifact(packageName, file.toUri()); + return file; + } + + private String packageNameFromFileName(String fn) { + StringBuilder sb = new StringBuilder(); + int p = fn.indexOf('_'), pp = 0; + while (p != -1) { + if (sb.length() > 0) sb.append('.'); + sb.append(fn.substring(pp,p)); + if (p == fn.length()-1) break; + pp = p+1; + p = fn.indexOf('_',pp); + } + return sb.toString(); + } + + @Override + public void flush() throws IOException { + super.flush(); + } + + @Override + public void close() throws IOException { + super.close(); + } + + void addArtifact(String pkgName, URI art) { + Set s = packageArtifacts.get(pkgName); + if (s == null) { + s = new HashSet(); + packageArtifacts.put(pkgName, s); + } + s.add(art); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java b/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java new file mode 100644 index 00000000000..17c22ede2a2 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.comp; + +import java.io.*; +import java.net.URI; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.NestingKind; +import javax.tools.JavaFileObject; + +/** + * The SmartFileObject will return an outputstream that cache the written data + * and compare the new content with the old content on disk. Only if they differ, + * will the file be updated. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class SmartFileObject implements JavaFileObject { + + JavaFileObject file; + PrintWriter stdout; + + public SmartFileObject(JavaFileObject r, PrintWriter pw) { + file = r; + stdout = pw; + } + + @Override + public boolean equals(Object other) { + return file.equals(other); + } + + @Override + public int hashCode() { + return file.hashCode(); + } + + public Kind getKind() { + return file.getKind(); + } + + public boolean isNameCompatible(String simpleName, Kind kind) { + return file.isNameCompatible(simpleName, kind); + } + + public URI toUri() { + return file.toUri(); + } + + public String getName() { + return file.getName(); + } + + public InputStream openInputStream() throws IOException { + return file.openInputStream(); + } + + public OutputStream openOutputStream() throws IOException { + return file.openOutputStream(); + } + + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return file.getCharContent(ignoreEncodingErrors); + } + + static String lineseparator = System.getProperty("line.separator"); + + public Writer openWriter() throws IOException { + StringBuilder s = new StringBuilder(); + try (BufferedReader r = new BufferedReader(file.openReader(true))) { + while (r.ready()) { + s.append(r.readLine()+lineseparator); + } + } catch (FileNotFoundException e) { + // Perfectly ok. + } + return new SmartWriter(file, s.toString(), file.getName(), stdout); + } + + public long getLastModified() { + return file.getLastModified(); + } + + public boolean delete() { + return file.delete(); + } + + public Modifier getAccessLevel() { + return file.getAccessLevel(); + } + + public NestingKind getNestingKind() { + return file.getNestingKind(); + } + + public Reader openReader(boolean ignoreEncodingErrors) throws IOException { + return file.openReader(ignoreEncodingErrors); + } + +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java b/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java new file mode 100644 index 00000000000..45bccfadf74 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.comp; + +import java.io.*; +import javax.tools.JavaFileObject; + +/** + * The SmartWriter will cache the written data and when the writer is closed, + * then it will compare the cached data with the old_content string. + * If different, then it will write all the new content to the file. + * If not, the file is not touched. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class SmartWriter extends Writer { + + String name; + JavaFileObject file; + String oldContent; + StringWriter newContent = new StringWriter(); + PrintWriter stdout; + boolean closed; + public SmartWriter(JavaFileObject f, String s, String n, PrintWriter pw) { + name = n; + file = f; + oldContent = s; + newContent = new StringWriter(); + stdout = pw; + closed = false; + } + + public void write(char[] chars, int i, int i1) + { + newContent.write(chars, i, i1); + } + + public void close() throws IOException { + if (closed) return; + closed = true; + String s = newContent.toString(); + if (!oldContent.equals(s)) { + int p = file.getName().lastIndexOf(File.separatorChar); + try (Writer writer = file.openWriter()) { + writer.write(s); + } + stdout.println("Writing "+file.getName().substring(p+1)); + } + } + + public void flush() throws IOException { + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerPool.java b/langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerPool.java new file mode 100644 index 00000000000..f0f0dcf6964 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerPool.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.server; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; +import java.util.Stack; +import java.util.concurrent.Future; + +/** The compiler pool maintains compiler threads. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class CompilerPool { + // The javac server that created this pool. + private JavacServer javacServer; + // A semaphore protecting the poolsize number of threads. + private Semaphore available; + // The stack of compiler threads. + private Stack compilers = new Stack(); + // And the executor server to spawn threads. + private final ExecutorService executorPool; + // How many requests are active right now? + private int concurrentRequests = 0; + // When was the last request finished? + private long lastRequestFinished = 0; + // The total number of requests to this pool. + private int numRequests = 0; + // Protect access to the three above values. + private static final Object conc = new Object(); + + /** + * Return the javac server that this pool belongs to. + */ + public JavacServer getJavacServer() { + return javacServer; + } + + /** + * Return how many threads are running at this very moment. + */ + public int numActiveRequests() + { + synchronized (conc) { + return concurrentRequests; + } + } + + /** + * Return when the last request was finished. + * I.e. the pool has been idle since. + */ + public long lastRequestFinished() + { + synchronized (conc) { + return lastRequestFinished; + } + } + + /** + * Up the number of active requests. + */ + public int startRequest() { + int n; + synchronized (conc) { + concurrentRequests++; + numRequests++; + n = numRequests; + } + return n; + } + + /** + * Down the number of active requests. Return the current time. + */ + public long stopRequest() { + synchronized (conc) { + concurrentRequests--; + lastRequestFinished = System.currentTimeMillis(); + } + return lastRequestFinished; + } + + /** + * Create a new compiler pool. + */ + CompilerPool(int poolsize, JavacServer server) { + available = new Semaphore(poolsize, true); + javacServer = server; + executorPool = Executors.newFixedThreadPool(poolsize); + lastRequestFinished = System.currentTimeMillis(); + } + + /** + * Execute a compiler thread. + */ + public void execute(CompilerThread ct) { + executorPool.execute(ct); + } + + /** + * Execute a minor task, for example generating bytecodes and writing them to disk, + * that belong to a major compiler thread task. + */ + public Future executeSubtask(CompilerThread t, Runnable r) { + return executorPool.submit(r); + } + + /** + * Shutdown the pool. + */ + public void shutdown() { + executorPool.shutdown(); + } + + /** + * Acquire a compiler thread from the pool, or block until a thread is available. + * If the pools is empty, create a new thread, but never more than is "available". + */ + public CompilerThread grabCompilerThread() throws InterruptedException { + available.acquire(); + if (compilers.empty()) { + return new CompilerThread(this); + } + return compilers.pop(); + } + + /** + * Return the specified compiler thread to the pool. + */ + public void returnCompilerThread(CompilerThread h) { + compilers.push(h); + available.release(); + } +} + diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerThread.java b/langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerThread.java new file mode 100644 index 00000000000..0a7a76f10b8 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/server/CompilerThread.java @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.server; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.Map; +import java.util.concurrent.Future; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.BaseFileManager; +import com.sun.tools.sjavac.comp.Dependencies; +import com.sun.tools.sjavac.comp.JavaCompilerWithDeps; +import com.sun.tools.sjavac.comp.SmartFileManager; +import com.sun.tools.sjavac.comp.ResolveWithDeps; + +/** + * The compiler thread maintains a JavaCompiler instance and + * can receive a request from the client, perform the compilation + * requested and report back the results. + * + * *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class CompilerThread implements Runnable { + private JavacServer javacServer; + private CompilerPool compilerPool; + private List> subTasks; + + // Communicating over this socket. + private Socket socket; + + // The necessary classes to do a compilation. + private com.sun.tools.javac.api.JavacTool compiler; + private StandardJavaFileManager fileManager; + private BaseFileManager fileManagerBase; + private SmartFileManager smartFileManager; + private Context context; + + // If true, then this thread is serving a request. + private boolean inUse = false; + + CompilerThread(CompilerPool cp) { + compilerPool = cp; + javacServer = cp.getJavacServer(); + } + + /** + * Execute a minor task, for example generating bytecodes and writing them to disk, + * that belong to a major compiler thread task. + */ + public synchronized void executeSubtask(Runnable r) { + subTasks.add(compilerPool.executeSubtask(this, r)); + } + + /** + * Count the number of active sub tasks. + */ + public synchronized int numActiveSubTasks() { + int c = 0; + for (Future f : subTasks) { + if (!f.isDone() && !f.isCancelled()) { + c++; + } + } + return c; + } + + /** + * Use this socket for the upcoming request. + */ + public void setSocket(Socket s) { + socket = s; + } + + /** + * Prepare the compiler thread for use. It is not yet started. + * It will be started by the executor service. + */ + public synchronized void use() { + assert(!inUse); + inUse = true; + compiler = com.sun.tools.javac.api.JavacTool.create(); + fileManager = compiler.getStandardFileManager(null, null, null); + fileManagerBase = (BaseFileManager)fileManager; + smartFileManager = new SmartFileManager(fileManager); + context = new Context(); + context.put(JavaFileManager.class, smartFileManager); + ResolveWithDeps.preRegister(context); + JavaCompilerWithDeps.preRegister(context, this); + subTasks = new ArrayList>(); + } + + /** + * Prepare the compiler thread for idleness. + */ + public synchronized void unuse() { + assert(inUse); + inUse = false; + compiler = null; + fileManager = null; + fileManagerBase = null; + smartFileManager = null; + context = null; + subTasks = null; + } + + /** + * Expect this key on the next line read from the reader. + */ + private static boolean expect(BufferedReader in, String key) throws IOException { + String s = in.readLine(); + if (s != null && s.equals(key)) { + return true; + } + return false; + } + + // The request identifier, for example GENERATE_NEWBYTECODE + String id = ""; + + public String currentRequestId() { + return id; + } + + PrintWriter stdout; + PrintWriter stderr; + int forcedExitCode = 0; + + public void logError(String msg) { + stderr.println(msg); + forcedExitCode = -1; + } + + /** + * Invoked by the executor service. + */ + public void run() { + // Unique nr that identifies this request. + int thisRequest = compilerPool.startRequest(); + long start = System.currentTimeMillis(); + int numClasses = 0; + StringBuilder compiledPkgs = new StringBuilder(); + use(); + + PrintWriter out = null; + try { + javacServer.log("<"+thisRequest+"> Connect from "+socket.getRemoteSocketAddress()+" activethreads="+compilerPool.numActiveRequests()); + BufferedReader in = new BufferedReader(new InputStreamReader( + socket.getInputStream())); + out = new PrintWriter(new OutputStreamWriter( + socket.getOutputStream())); + if (!expect(in, JavacServer.PROTOCOL_COOKIE_VERSION)) { + javacServer.log("<"+thisRequest+"> Bad protocol from ip "+socket.getRemoteSocketAddress()); + return; + } + + String cookie = in.readLine(); + if (cookie == null || !cookie.equals(""+javacServer.getCookie())) { + javacServer.log("<"+thisRequest+"> Bad cookie from ip "+socket.getRemoteSocketAddress()); + return; + } + if (!expect(in, JavacServer.PROTOCOL_CWD)) { + return; + } + String cwd = in.readLine(); + if (cwd == null) + return; + if (!expect(in, JavacServer.PROTOCOL_ID)) { + return; + } + id = in.readLine(); + if (id == null) + return; + if (!expect(in, JavacServer.PROTOCOL_ARGS)) { + return; + } + ArrayList the_options = new ArrayList(); + ArrayList the_classes = new ArrayList(); + Iterable path = Arrays. asList(new File(cwd)); + + for (;;) { + String l = in.readLine(); + if (l == null) + return; + if (l.equals(JavacServer.PROTOCOL_SOURCES_TO_COMPILE)) + break; + if (l.startsWith("--server:")) + continue; + if (!l.startsWith("-") && l.endsWith(".java")) { + the_classes.add(new File(l)); + numClasses++; + } else { + the_options.add(l); + } + continue; + } + + // Load sources to compile + Set sourcesToCompile = new HashSet(); + for (;;) { + String l = in.readLine(); + if (l == null) + return; + if (l.equals(JavacServer.PROTOCOL_VISIBLE_SOURCES)) + break; + try { + sourcesToCompile.add(new URI(l)); + numClasses++; + } catch (URISyntaxException e) { + return; + } + } + // Load visible sources + Set visibleSources = new HashSet(); + boolean fix_drive_letter_case = System.getProperty("os.name").toLowerCase().equals("windows"); + for (;;) { + String l = in.readLine(); + if (l == null) + return; + if (l.equals(JavacServer.PROTOCOL_END)) + break; + try { + URI u = new URI(l); + if (fix_drive_letter_case) { + // Make sure the driver letter is lower case. + String s = u.toString(); + if (s.startsWith("file:/") && + Character.isUpperCase(s.charAt(6))) { + u = new URI("file:/"+Character.toLowerCase(s.charAt(6))+s.substring(7)); + } + } + visibleSources.add(u); + } catch (URISyntaxException e) { + return; + } + } + + // A completed request has been received. + + // Now setup the actual compilation.... + // First deal with explicit source files on cmdline and in at file. + com.sun.tools.javac.util.ListBuffer compilationUnits = + new com.sun.tools.javac.util.ListBuffer(); + for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(the_classes)) { + compilationUnits.append(i); + } + // Now deal with sources supplied as source_to_compile. + com.sun.tools.javac.util.ListBuffer sourcesToCompileFiles = + new com.sun.tools.javac.util.ListBuffer(); + for (URI u : sourcesToCompile) { + sourcesToCompileFiles.append(new File(u)); + } + for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) { + compilationUnits.append(i); + } + // Log the options to be used. + StringBuilder options = new StringBuilder(); + for (String s : the_options) { + options.append(">").append(s).append("< "); + } + javacServer.log(id+" <"+thisRequest+"> options "+options.toString()); + + forcedExitCode = 0; + // Create a new logger. + StringWriter stdoutLog = new StringWriter(); + StringWriter stderrLog = new StringWriter(); + stdout = new PrintWriter(stdoutLog); + stderr = new PrintWriter(stderrLog); + com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; + try { + if (compilationUnits.size() > 0) { + // Bind the new logger to the existing context. + context.put(Log.outKey, stderr); + Log.instance(context).setWriter(Log.WriterKind.NOTICE, stdout); + Log.instance(context).setWriter(Log.WriterKind.WARNING, stderr); + Log.instance(context).setWriter(Log.WriterKind.ERROR, stderr); + // Process the options. + com.sun.tools.javac.api.JavacTool.processOptions(context, smartFileManager, the_options); + fileManagerBase.setContext(context); + smartFileManager.setVisibleSources(visibleSources); + smartFileManager.cleanArtifacts(); + smartFileManager.setLog(stdout); + Dependencies.instance(context).reset(); + + com.sun.tools.javac.main.Main ccompiler = new com.sun.tools.javac.main.Main("javacTask", stderr); + String[] aa = the_options.toArray(new String[0]); + + // Do the compilation! + rc = ccompiler.compile(aa, context, compilationUnits.toList(), null); + + while (numActiveSubTasks()>0) { + try { Thread.sleep(1000); } catch (InterruptedException e) { } + } + + smartFileManager.flush(); + } + } catch (Exception e) { + stderr.println(e.getMessage()); + forcedExitCode = -1; + } + + // Send the response.. + out.println(JavacServer.PROTOCOL_STDOUT); + out.print(stdoutLog); + out.println(JavacServer.PROTOCOL_STDERR); + out.print(stderrLog); + // The compilation is complete! And errors will have already been printed on out! + out.println(JavacServer.PROTOCOL_PACKAGE_ARTIFACTS); + Map> pa = smartFileManager.getPackageArtifacts(); + for (String aPkgName : pa.keySet()) { + out.println("+"+aPkgName); + Set as = pa.get(aPkgName); + for (URI a : as) { + out.println(" "+a.toString()); + } + } + Dependencies deps = Dependencies.instance(context); + out.println(JavacServer.PROTOCOL_PACKAGE_DEPENDENCIES); + Map> pd = deps.getDependencies(); + for (String aPkgName : pd.keySet()) { + out.println("+"+aPkgName); + Set ds = pd.get(aPkgName); + // Everything depends on java.lang + if (!ds.contains(":java.lang")) ds.add(":java.lang"); + for (String d : ds) { + out.println(" "+d); + } + } + out.println(JavacServer.PROTOCOL_PACKAGE_PUBLIC_APIS); + Map pp = deps.getPubapis(); + for (String aPkgName : pp.keySet()) { + out.println("+"+aPkgName); + String ps = pp.get(aPkgName); + // getPubapis added a space to each line! + out.println(ps); + compiledPkgs.append(aPkgName+" "); + } + out.println(JavacServer.PROTOCOL_SYSINFO); + out.println("num_cores=" + Runtime.getRuntime().availableProcessors()); + out.println("max_memory=" + Runtime.getRuntime().maxMemory()); + out.println(JavacServer.PROTOCOL_RETURN_CODE); + + // Errors from sjavac that affect compilation status! + int rcv = rc.exitCode; + if (rcv == 0 && forcedExitCode != 0) { + rcv = forcedExitCode; + } + out.println("" + rcv); + out.println(JavacServer.PROTOCOL_END); + out.flush(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (out != null) out.close(); + if (!socket.isClosed()) { + socket.close(); + } + socket = null; + } catch (Exception e) { + javacServer.log("ERROR "+e); + e.printStackTrace(); + } + compilerPool.stopRequest(); + long duration = System.currentTimeMillis()-start; + javacServer.addBuildTime(duration); + float classpersec = ((float)numClasses)*(((float)1000.0)/((float)duration)); + javacServer.log(id+" <"+thisRequest+"> "+compiledPkgs+" duration " + duration+ " ms num_classes="+numClasses+ + " classpersec="+classpersec+" subtasks="+subTasks.size()); + javacServer.flushLog(); + unuse(); + compilerPool.returnCompilerThread(this); + } + } +} + diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java b/langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java new file mode 100644 index 00000000000..2e59f275fd8 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java @@ -0,0 +1,751 @@ +/* + * Copyright (c) 2011-2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.server; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.FileNotFoundException; +import java.net.URI; +import java.util.HashSet; +import java.util.Set; +import java.util.HashMap; +import java.util.Map; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.Random; + +import com.sun.tools.sjavac.Util; +import com.sun.tools.sjavac.ProblemException; +import java.io.*; +import java.util.*; + +/** + * The JavacServer class contains methods both to setup a server that responds to requests and methods to connect to this server. + * + *

This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are + * subject to change or deletion without notice.

+ */ +public class JavacServer { + // Responding to this tcp/ip port on localhost. + + private final ServerSocket serverSocket; + // The secret cookie shared between server and client through the port file. + private final long myCookie; + // When the server was started. + private long serverStart; + // Accumulated build time for all requests, not counting idle time. + private long totalBuildTime; + // The javac server specific log file. + PrintWriter theLog; + // The compiler pool that maintains the compiler threads. + CompilerPool compilerPool; + // For the client, all port files fetched, one per started javac server. + // Though usually only one javac server is started by a client. + private static Map allPortFiles; + private static Map maxServerMemory; + final static int ERROR_FATAL = -1; + final static int ERROR_BUT_TRY_AGAIN = -4712; + final static String PROTOCOL_COOKIE_VERSION = "----THE-COOKIE-V2----"; + final static String PROTOCOL_CWD = "----THE-CWD----"; + final static String PROTOCOL_ID = "----THE-ID----"; + final static String PROTOCOL_ARGS = "----THE-ARGS----"; + final static String PROTOCOL_SOURCES_TO_COMPILE = "----THE-SOURCES-TO-COMPILE----"; + final static String PROTOCOL_VISIBLE_SOURCES = "----THE-VISIBLE-SOURCES----"; + final static String PROTOCOL_END = "----THE-END----"; + final static String PROTOCOL_STDOUT = "----THE-STDOUT----"; + final static String PROTOCOL_STDERR = "----THE-STDERR----"; + final static String PROTOCOL_PACKAGE_ARTIFACTS = "----THE-PACKAGE_ARTIFACTS----"; + final static String PROTOCOL_PACKAGE_DEPENDENCIES = "----THE-PACKAGE_DEPENDENCIES----"; + final static String PROTOCOL_PACKAGE_PUBLIC_APIS = "----THE-PACKAGE-PUBLIC-APIS----"; + final static String PROTOCOL_SYSINFO = "----THE-SYSINFO----"; + final static String PROTOCOL_RETURN_CODE = "----THE-RETURN-CODE----"; + // Check if the portfile is gone, every 5 seconds. + static int CHECK_PORTFILE_INTERVAL = 5; + // Wait 2 seconds for response, before giving up on javac server. + static int CONNECTION_TIMEOUT = 2; + static int WAIT_BETWEEN_CONNECT_ATTEMPTS = 1; + static int MAX_NUM_CONNECT_ATTEMPTS = 3; + + /** + * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. + */ + private static synchronized PortFile getPortFile(String filename) throws FileNotFoundException { + if (allPortFiles == null) { + allPortFiles = new HashMap(); + } + PortFile pf = allPortFiles.get(filename); + if (pf == null) { + pf = new PortFile(filename); + allPortFiles.put(filename, pf); + } + return pf; + } + + /** + * Get the cookie used for this server. + */ + long getCookie() { + return myCookie; + } + + /** + * Get the port used for this server. + */ + int getPort() { + return serverSocket.getLocalPort(); + } + + /** + * Sum up the total build time for this javac server. + */ + public void addBuildTime(long inc) { + totalBuildTime += inc; + } + + /** + * Log this message. + */ + public void log(String msg) { + if (theLog != null) { + theLog.println(msg); + } else { + System.err.println(msg); + } + } + + /** + * Make sure the log is flushed. + */ + public void flushLog() { + if (theLog != null) { + theLog.flush(); + } + } + + /** + * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" + * is sent as the settings parameter. Returns 0 on success, -1 on failure. + */ + public static int startServer(String settings, PrintStream err) { + try { + String portfile = Util.extractStringOption("portfile", settings); + // The log file collects more javac server specific log information. + String logfile = Util.extractStringOption("logfile", settings); + // The stdouterr file collects all the System.out and System.err writes to disk. + String stdouterrfile = Util.extractStringOption("stdouterrfile", settings); + // We could perhaps use System.setOut and setErr here. + // But for the moment we rely on the client to spawn a shell where stdout + // and stderr are redirected already. + // The pool size is a limit the number of concurrent compiler threads used. + // The server might use less than these to avoid memory problems. + int poolsize = Util.extractIntOption("poolsize", settings); + if (poolsize <= 0) { + // If not set, default to the number of cores. + poolsize = Runtime.getRuntime().availableProcessors(); + } + + // How many seconds of inactivity will the server accept before quitting? + int keepalive = Util.extractIntOption("keepalive", settings); + if (keepalive <= 0) { + keepalive = 120; + } + // The port file is locked and the server port and cookie is written into it. + PortFile portFile = getPortFile(portfile); + JavacServer s; + + synchronized (portFile) { + portFile.lock(); + portFile.getValues(); + if (portFile.containsPortInfo()) { + err.println("Javac server not started because portfile exists!"); + portFile.unlock(); + return -1; + } + s = new JavacServer(poolsize, logfile); + portFile.setValues(s.getPort(), s.getCookie()); + portFile.unlock(); + } + + // Run the server. Will delete the port file when shutting down. + // It will shut down automatically when no new requests have come in + // during the last 125 seconds. + s.run(portFile, err, keepalive); + // The run loop for the server has exited. + return 0; + } catch (Exception e) { + e.printStackTrace(err); + return -1; + } + } + + /** + * Dispatch a compilation request to a javac server. + * + * @param args are the command line args to javac and is allowed to contain source files, @file and other command line options to javac. + * + * The generated classes, h files and other artifacts from the javac invocation are stored by the javac server to disk. + * + * @param sources_to_compile The sources to compile. + * + * @param visibleSources If visible sources has a non zero size, then visible_sources are the only files in the file system that the javac server can see! + * (Sources to compile are always visible.) The visible sources are those supplied by the (filtered) -sourcepath + * + * @param visibleClasses If visible classes for a specific root/jar has a non zero size, then visible_classes are the only class files that the javac server + * can see, in that root/jar. It maps from a classpath root or a jar file to the set of visible classes for that root/jar. + * + * The server return meta data about the build in the following parameters. + * @param package_artifacts, map from package name to set of created artifacts for that package. + * @param package_dependencies, map from package name to set of packages that it depends upon. + * @param package_pubapis, map from package name to unique string identifying its pub api. + */ + public static int useServer(String settings, String[] args, + Set sourcesToCompile, + Set visibleSources, + Map> visibleClasses, + Map> packageArtifacts, + Map> packageDependencies, + Map packagePubapis, + SysInfo sysinfo, + PrintStream out, + PrintStream err) { + try { + // The id can perhaps be used in the future by the javac server to reuse the + // JavaCompiler instance for several compiles using the same id. + String id = Util.extractStringOption("id", settings); + String portfile = Util.extractStringOption("portfile", settings); + String logfile = Util.extractStringOption("logfile", settings); + String stdouterrfile = Util.extractStringOption("stdouterrfile", settings); + String background = Util.extractStringOption("background", settings); + if (background == null || !background.equals("false")) { + background = "true"; + } + // The sjavac option specifies how the server part of sjavac is spawned. + // If you have the experimental sjavac in your path, you are done. If not, you have + // to point to a com.sun.tools.sjavac.Main that supports --startserver + // for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main + String sjavac = Util.extractStringOption("sjavac", settings); + int poolsize = Util.extractIntOption("poolsize", settings); + int keepalive = Util.extractIntOption("keepalive", settings); + + if (keepalive <= 0) { + // Default keepalive for server is 120 seconds. + // I.e. it will accept 120 seconds of inactivity before quitting. + keepalive = 120; + } + if (portfile == null) { + err.println("No portfile was specified!"); + return -1; + } + if (logfile == null) { + logfile = portfile + ".javaclog"; + } + if (stdouterrfile == null) { + stdouterrfile = portfile + ".stdouterr"; + } + // Default to sjavac and hope it is in the path. + if (sjavac == null) { + sjavac = "sjavac"; + } + + int attempts = 0; + int rc = -1; + do { + PortFile port_file = getPortFile(portfile); + synchronized (port_file) { + port_file.lock(); + port_file.getValues(); + port_file.unlock(); + } + if (!port_file.containsPortInfo()) { + String cmd = fork(sjavac, port_file.getFilename(), logfile, poolsize, keepalive, err, stdouterrfile, background); + + if (background.equals("true") && !port_file.waitForValidValues()) { + // Ouch the server did not start! Lets print its stdouterrfile and the command used. + printFailedAttempt(cmd, stdouterrfile, err); + // And give up. + return -1; + } + } + rc = connectAndCompile(port_file, id, args, sourcesToCompile, visibleSources, + packageArtifacts, packageDependencies, packagePubapis, sysinfo, + out, err); + // Try again until we manage to connect. Any error after that + // will cause the compilation to fail. + if (rc == ERROR_BUT_TRY_AGAIN) { + // We could not connect to the server. Try again. + attempts++; + try { + Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS); + } catch (InterruptedException e) { + } + } + } while (rc == ERROR_BUT_TRY_AGAIN && attempts < MAX_NUM_CONNECT_ATTEMPTS); + return rc; + } catch (Exception e) { + e.printStackTrace(err); + return -1; + } + } + + private static void printFailedAttempt(String cmd, String f, PrintStream err) { + err.println("---- Failed to start javac server with this command -----"); + err.println(cmd); + try { + BufferedReader in = new BufferedReader(new FileReader(f)); + err.println("---- stdout/stderr output from attempt to start javac server -----"); + for (;;) { + String l = in.readLine(); + if (l == null) { + break; + } + err.println(l); + } + err.println("------------------------------------------------------------------"); + } catch (Exception e) { + err.println("The stdout/stderr output in file " + f + " does not exist and the server did not start."); + } + } + + /** + * Spawn the server instance. + */ + + private JavacServer(int poolSize, String logfile) throws IOException { + serverStart = System.currentTimeMillis(); + // Create a server socket on a random port that is bound to the localhost/127.0.0.1 interface. + // I.e only local processes can connect to this port. + serverSocket = new ServerSocket(0, 128, InetAddress.getByName(null)); + compilerPool = new CompilerPool(poolSize, this); + Random rnd = new Random(); + myCookie = rnd.nextLong(); + theLog = new PrintWriter(logfile); + log("Javac server started. port=" + getPort() + " date=" + (new java.util.Date()) + " with poolsize=" + poolSize); + flushLog(); + } + + /** + * Fork a background process. Returns the command line used that can be printed if something failed. + */ + private static String fork(String sjavac, String portfile, String logfile, int poolsize, int keepalive, + final PrintStream err, String stdouterrfile, String background) + throws IOException, ProblemException { + if (stdouterrfile != null && stdouterrfile.trim().equals("")) { + stdouterrfile = null; + } + final String startserver = "--startserver:portfile=" + portfile + ",logfile=" + logfile + ",stdouterrfile=" + stdouterrfile + ",poolsize=" + poolsize + ",keepalive="+ keepalive; + + if (background.equals("true")) { + sjavac += "%20" + startserver; + sjavac = sjavac.replaceAll("%20", " "); + sjavac = sjavac.replaceAll("%2C", ","); + // If the java/sh/cmd launcher fails the failure will be captured by stdouterr because of the redirection here. + String[] cmd = {"/bin/sh", "-c", sjavac + " >> " + stdouterrfile + " 2>&1"}; + if (!(new File("/bin/sh")).canExecute()) { + ArrayList wincmd = new ArrayList(); + wincmd.add("cmd"); + wincmd.add("/c"); + wincmd.add("start"); + wincmd.add("cmd"); + wincmd.add("/c"); + wincmd.add(sjavac + " >> " + stdouterrfile + " 2>&1"); + cmd = wincmd.toArray(new String[wincmd.size()]); + } + Process pp = null; + try { + pp = Runtime.getRuntime().exec(cmd); + } catch (Exception e) { + e.printStackTrace(err); + e.printStackTrace(new PrintWriter(stdouterrfile)); + } + StringBuilder rs = new StringBuilder(); + for (String s : cmd) { + rs.append(s + " "); + } + return rs.toString(); + } + + // Do not spawn a background server, instead run it within the same JVM. + Thread t = new Thread() { + @Override + public void run() { + try { + JavacServer.startServer(startserver, err); + } catch (Throwable t) { + t.printStackTrace(err); + } + } + }; + t.start(); + return ""; + } + + /** + * Expect this key on the next line read from the reader. + */ + private static boolean expect(BufferedReader in, String key) throws IOException { + String s = in.readLine(); + if (s != null && s.equals(key)) { + return true; + } + return false; + } + + /** + * Make a request to the server only to get the maximum possible heap size to use for compilations. + * + * @param port_file The port file used to synchronize creation of this server. + * @param id The identify of the compilation. + * @param out Standard out information. + * @param err Standard err information. + * @return The maximum heap size in bytes. + */ + public static SysInfo connectGetSysInfo(String serverSettings, PrintStream out, PrintStream err) { + SysInfo sysinfo = new SysInfo(-1, -1); + String id = Util.extractStringOption("id", serverSettings); + String portfile = Util.extractStringOption("portfile", serverSettings); + try { + PortFile pf = getPortFile(portfile); + useServer(serverSettings, new String[0], + new HashSet(), + new HashSet(), + new HashMap>(), + new HashMap>(), + new HashMap>(), + new HashMap(), + sysinfo, out, err); + } catch (Exception e) { + e.printStackTrace(err); + } + return sysinfo; + } + + /** + * Connect and compile using the javac server settings and the args. When using more advanced features, the sources_to_compile and visible_sources are + * supplied to the server and meta data is returned in package_artifacts, package_dependencies and package_pubapis. + */ + private static int connectAndCompile(PortFile portFile, String id, String[] args, + Set sourcesToCompile, + Set visibleSources, + Map> packageArtifacts, + Map> packageDependencies, + Map packagePublicApis, + SysInfo sysinfo, + PrintStream out, + PrintStream err) { + int rc = -3; + try { + int port = portFile.getPort(); + if (port == 0) { + return ERROR_BUT_TRY_AGAIN; + } + long cookie = portFile.getCookie(); + + // Acquire the localhost/127.0.0.1 address. + InetAddress addr = InetAddress.getByName(null); + SocketAddress sockaddr = new InetSocketAddress(addr, port); + Socket sock = new Socket(); + int timeoutMs = CONNECTION_TIMEOUT * 1000; + try { + sock.connect(sockaddr, timeoutMs); + } catch (java.net.ConnectException e) { + err.println("Could not connect to javac server found in portfile: " + portFile.getFilename() + " " + e); + return ERROR_BUT_TRY_AGAIN; + } + if (!sock.isConnected()) { + err.println("Could not connect to javac server found in portfile: " + portFile.getFilename()); + return ERROR_BUT_TRY_AGAIN; + } + BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream())); + PrintWriter sockout = new PrintWriter(sock.getOutputStream()); + + sockout.println(PROTOCOL_COOKIE_VERSION); + sockout.println("" + cookie); + sockout.println(PROTOCOL_CWD); + sockout.println(System.getProperty("user.dir")); + sockout.println(PROTOCOL_ID); + sockout.println(id); + sockout.println(PROTOCOL_ARGS); + for (String s : args) { + StringBuffer buf = new StringBuffer(); + String[] paths = s.split(File.pathSeparator); + int c = 0; + for (String path : paths) { + File f = new File(path); + if (f.isFile() || f.isDirectory()) { + buf.append(f.getAbsolutePath()); + c++; + if (c < paths.length) { + buf.append(File.pathSeparator); + } + } else { + buf = new StringBuffer(s); + break; + } + } + sockout.println(buf.toString()); + } + sockout.println(PROTOCOL_SOURCES_TO_COMPILE); + for (URI uri : sourcesToCompile) { + sockout.println(uri.toString()); + } + sockout.println(PROTOCOL_VISIBLE_SOURCES); + for (URI uri : visibleSources) { + sockout.println(uri.toString()); + } + sockout.println(PROTOCOL_END); + sockout.flush(); + + StringBuffer stdout = new StringBuffer(); + StringBuffer stderr = new StringBuffer(); + + if (!expect(in, PROTOCOL_STDOUT)) { + return ERROR_FATAL; + } + // Load stdout + for (;;) { + String l = in.readLine(); + if (l == null) { + return ERROR_FATAL; + } + if (l.equals(PROTOCOL_STDERR)) { + break; + } + stdout.append(l); + stdout.append('\n'); + } + // Load stderr + for (;;) { + String l = in.readLine(); + if (l == null) { + return ERROR_FATAL; + } + if (l.equals(PROTOCOL_PACKAGE_ARTIFACTS)) { + break; + } + stderr.append(l); + stderr.append('\n'); + } + // Load the package artifacts + Set lastUriSet = null; + for (;;) { + String l = in.readLine(); + if (l == null) { + return ERROR_FATAL; + } + if (l.equals(PROTOCOL_PACKAGE_DEPENDENCIES)) { + break; + } + if (l.length() > 1 && l.charAt(0) == '+') { + String pkg = l.substring(1); + lastUriSet = new HashSet(); + packageArtifacts.put(pkg, lastUriSet); + } else if (l.length() > 1 && lastUriSet != null) { + lastUriSet.add(new URI(l.substring(1))); + } + } + // Load package dependencies + Set lastPackageSet = null; + for (;;) { + String l = in.readLine(); + if (l == null) { + return ERROR_FATAL; + } + if (l.equals(PROTOCOL_PACKAGE_PUBLIC_APIS)) { + break; + } + if (l.length() > 1 && l.charAt(0) == '+') { + String pkg = l.substring(1); + lastPackageSet = new HashSet(); + packageDependencies.put(pkg, lastPackageSet); + } else if (l.length() > 1 && lastPackageSet != null) { + lastPackageSet.add(l.substring(1)); + } + } + // Load package pubapis + Map tmp = new HashMap(); + StringBuffer lastPublicApi = null; + for (;;) { + String l = in.readLine(); + if (l == null) { + return ERROR_FATAL; + } + if (l.equals(PROTOCOL_SYSINFO)) { + break; + } + if (l.length() > 1 && l.charAt(0) == '+') { + String pkg = l.substring(1); + lastPublicApi = new StringBuffer(); + tmp.put(pkg, lastPublicApi); + } else if (l.length() > 1 && lastPublicApi != null) { + lastPublicApi.append(l.substring(1)); + lastPublicApi.append("\n"); + } + } + for (String p : tmp.keySet()) { + assert (packagePublicApis.get(p) == null); + String api = tmp.get(p).toString(); + packagePublicApis.put(p, api); + } + // Now reading the max memory possible. + for (;;) { + String l = in.readLine(); + if (l == null) { + return ERROR_FATAL; + } + if (l.equals(PROTOCOL_RETURN_CODE)) { + break; + } + if (l.startsWith("num_cores=") && sysinfo != null) { + sysinfo.numCores = Integer.parseInt(l.substring(10)); + } + if (l.startsWith("max_memory=") && sysinfo != null) { + sysinfo.maxMemory = Long.parseLong(l.substring(11)); + } + } + String l = in.readLine(); + if (l == null) { + err.println("No return value from the server!"); + return ERROR_FATAL; + } + rc = Integer.parseInt(l); + out.print(stdout); + err.print(stderr); + } catch (Exception e) { + e.printStackTrace(err); + } + return rc; + } + + /** + * Run the server thread until it exits. Either because of inactivity or because the port file has been deleted by someone else, or overtaken by some other + * javac server. + */ + private void run(PortFile portFile, PrintStream err, int keepalive) { + boolean fileDeleted = false; + long timeSinceLastCompile; + try { + // Every 5 second (check_portfile_interval) we test if the portfile has disappeared => quit + // Or if the last request was finished more than 125 seconds ago => quit + // 125 = seconds_of_inactivity_before_shutdown+check_portfile_interval + serverSocket.setSoTimeout(CHECK_PORTFILE_INTERVAL*1000); + for (;;) { + try { + Socket s = serverSocket.accept(); + CompilerThread ct = compilerPool.grabCompilerThread(); + ct.setSocket(s); + compilerPool.execute(ct); + flushLog(); + } catch (java.net.SocketTimeoutException e) { + if (compilerPool.numActiveRequests() > 0) { + // Never quit while there are active requests! + continue; + } + // If this is the timeout after the portfile + // has been deleted by us. Then we truly stop. + if (fileDeleted) { + log("Quitting because of "+(keepalive+CHECK_PORTFILE_INTERVAL)+" seconds of inactivity!"); + break; + } + // Check if the portfile is still there. + if (!portFile.exists()) { + // Time to quit because the portfile was deleted by another + // process, probably by the makefile that is done building. + log("Quitting because portfile was deleted!"); + flushLog(); + break; + } + // Check if portfile.stop is still there. + if (portFile.markedForStop()) { + // Time to quit because another process touched the file + // server.port.stop to signal that the server should stop. + // This is necessary on some operating systems that lock + // the port file hard! + log("Quitting because a portfile.stop file was found!"); + portFile.delete(); + flushLog(); + break; + } + // Does the portfile still point to me? + if (!portFile.stillMyValues()) { + // Time to quit because another build has started. + log("Quitting because portfile is now owned by another javac server!"); + flushLog(); + break; + } + + // Check how long since the last request finished. + long diff = System.currentTimeMillis() - compilerPool.lastRequestFinished(); + if (diff < keepalive * 1000) { + // Do not quit if we have waited less than 120 seconds. + continue; + } + // Ok, time to quit because of inactivity. Perhaps the build + // was killed and the portfile not cleaned up properly. + portFile.delete(); + fileDeleted = true; + log("" + keepalive + " seconds of inactivity quitting in " + + CHECK_PORTFILE_INTERVAL + " seconds!"); + flushLog(); + // Now we have a second 5 second grace + // period where javac remote requests + // that have loaded the data from the + // recently deleted portfile can connect + // and complete their requests. + } + } + } catch (Exception e) { + e.printStackTrace(err); + e.printStackTrace(theLog); + flushLog(); + } finally { + compilerPool.shutdown(); + } + long realTime = System.currentTimeMillis() - serverStart; + log("Shutting down."); + log("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); + flushLog(); + } + + public static void cleanup(String... args) { + String settings = Util.findServerSettings(args); + if (settings == null) return; + String portfile = Util.extractStringOption("portfile", settings); + String background = Util.extractStringOption("background", settings); + if (background != null && background.equals("false")) { + // If the server runs within this jvm, then delete the portfile, + // since this jvm is about to exit soon. + File f = new File(portfile); + f.delete(); + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/server/PortFile.java b/langtools/src/share/classes/com/sun/tools/sjavac/server/PortFile.java new file mode 100644 index 00000000000..fa5b3692254 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/server/PortFile.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.sjavac.server; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.FileLockInterruptionException; +import com.sun.tools.sjavac.Log; + +/** + * The PortFile class mediates access to a short binary file containing the tcp/ip port (for the localhost) + * and a cookie necessary for the server answering on that port. The file can be locked using file system + * primitives to avoid race conditions when several javac clients are started at the same. Note that file + * system locking is not always supported on a all operating systems and/or file systems. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +class PortFile { + + // Port file format: + // byte ordering: high byte first = big endian + // Magic nr, 4 byte int, first in file. + private final static int magicNr = 0x1174; + // Followed by a 4 byte int, with the port nr. + // Followed by a 8 byte long, with cookie nr. + + private String filename; + private File file; + private File stopFile; + private RandomAccessFile rwfile; + private FileChannel channel; + private FileLock lock; + + private boolean containsPortInfo; + private int serverPort; + private long serverCookie; + private int myServerPort; + private long myServerCookie; + + /** + * Create a new portfile. + * @param filename is the path to the file. + */ + public PortFile(String fn) throws FileNotFoundException + { + filename = fn; + file = new File(filename); + stopFile = new File(filename+".stop"); + rwfile = new RandomAccessFile(file, "rw"); + // The rwfile should only be readable by the owner of the process + // and no other! How do we do that on a RandomAccessFile? + channel = rwfile.getChannel(); + containsPortInfo = false; + lock = null; + } + + /** + * Lock the port file. + */ + void lock() throws IOException { + lock = channel.lock(); + } + + /** + * Read the values from the port file in the file system. + * Expects the port file to be locked. + */ + public void getValues() { + containsPortInfo = false; + if (lock == null) { + // Not locked, remain ignorant about port file contents. + return; + } + try { + if (rwfile.length()>0) { + rwfile.seek(0); + int nr = rwfile.readInt(); + serverPort = rwfile.readInt(); + serverCookie = rwfile.readLong(); + + if (nr == magicNr) { + containsPortInfo = true; + } else { + containsPortInfo = false; + } + } + } catch (Exception e) { + containsPortInfo = false; + } + } + + /** + * Did the locking and getValues succeed? + */ + public boolean containsPortInfo() { + return containsPortInfo; + } + + /** + * If so, then we can acquire the tcp/ip port on localhost. + */ + public int getPort() { + assert(containsPortInfo); + return serverPort; + } + + /** + * If so, then we can acquire the server cookie. + */ + public long getCookie() { + assert(containsPortInfo); + return serverCookie; + } + + /** + * Store the values into the locked port file. + */ + public void setValues(int port, long cookie) throws IOException { + assert(lock != null); + rwfile.seek(0); + // Write the magic nr that identifes a port file. + rwfile.writeInt(magicNr); + rwfile.writeInt(port); + rwfile.writeLong(cookie); + myServerPort = port; + myServerCookie = cookie; + } + + /** + * Delete the port file. + */ + public void delete() throws IOException { + // Access to file must be closed before deleting. + rwfile.close(); + // Now delete. + file.delete(); + } + + /** + * Is the port file still there? + */ + public boolean exists() throws IOException { + return file.exists(); + } + + /** + * Is a stop file there? + */ + public boolean markedForStop() throws IOException { + if (stopFile.exists()) { + try { + stopFile.delete(); + } catch (Exception e) + {} + return true; + } + return false; + } + + /** + * Unlock the port file. + */ + public void unlock() throws IOException { + assert(lock != null); + lock.release(); + lock = null; + } + + /** + * Wait for the port file to contain values that look valid. + * Return true, if a-ok, false if the valid values did not materialize within 5 seconds. + */ + public synchronized boolean waitForValidValues() throws IOException, FileNotFoundException { + for (int tries = 0; tries < 50; tries++) { + lock(); + getValues(); + unlock(); + if (containsPortInfo) { + Log.debug("Found valid values in port file after waiting "+(tries*100)+"ms"); + return true; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) + {} + } + Log.debug("Gave up waiting for valid values in port file"); + return false; + } + + /** + * Check if the portfile still contains my values, assuming that I am the server. + */ + public synchronized boolean stillMyValues() throws IOException, FileNotFoundException { + for (;;) { + try { + lock(); + getValues(); + unlock(); + if (containsPortInfo) { + if (serverPort == myServerPort && + serverCookie == myServerCookie) { + // Everything is ok. + return true; + } + // Someone has overwritten the port file. + // Probably another javac server, lets quit. + return false; + } + // Something else is wrong with the portfile. Lets quit. + return false; + } catch (FileLockInterruptionException e) { + continue; + } + catch (ClosedChannelException e) { + // The channel has been closed since sjavac is exiting. + return false; + } + } + } + + /** + * Return the name of the port file. + */ + public String getFilename() { + return filename; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/server/SysInfo.java b/langtools/src/share/classes/com/sun/tools/sjavac/server/SysInfo.java new file mode 100644 index 00000000000..3a792465d16 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/sjavac/server/SysInfo.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/** + * A utility class used to report information about the system + * where the javac server is running. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +package com.sun.tools.sjavac.server; + +public class SysInfo { + public int numCores; + public long maxMemory; + + public SysInfo(int nc, long mm) { + numCores = nc; + maxMemory = mm; + } +} diff --git a/langtools/src/share/classes/javax/lang/model/SourceVersion.java b/langtools/src/share/classes/javax/lang/model/SourceVersion.java index c810c9e6013..e2f3bfd538f 100644 --- a/langtools/src/share/classes/javax/lang/model/SourceVersion.java +++ b/langtools/src/share/classes/javax/lang/model/SourceVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -46,7 +46,7 @@ import java.util.HashSet; */ public enum SourceVersion { /* - * Summary of language evoluation + * Summary of language evolution * 1.1: nested classes * 1.2: strictfp * 1.3: no changes diff --git a/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java b/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java index 888ab35f397..6d01d0f1734 100644 --- a/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java +++ b/langtools/src/share/classes/javax/lang/model/element/AnnotationValueVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -61,6 +61,18 @@ import javax.lang.model.type.TypeMirror; * parameters, return type, etc. rather than one of the abstract * classes. * + *

Note that methods to accommodate new language constructs could + * be added in a source compatible way if they were added as + * default methods. However, default methods are only + * available on Java SE 8 and higher releases and the {@code + * javax.lang.model.*} packages bundled in Java SE 8 are required to + * also be runnable on Java SE 7. Therefore, default methods + * cannot be used when extending {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods may + * be used in subsequent revisions of the {@code javax.lang.model.*} + * packages that are only required to run on Java SE 8 and higher + * platform versions. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * @author Joseph D. Darcy diff --git a/langtools/src/share/classes/javax/lang/model/element/Element.java b/langtools/src/share/classes/javax/lang/model/element/Element.java index 505525865c5..a95cbe0ca95 100644 --- a/langtools/src/share/classes/javax/lang/model/element/Element.java +++ b/langtools/src/share/classes/javax/lang/model/element/Element.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -148,6 +148,56 @@ public interface Element { */ A getAnnotation(Class annotationType); + /** + * Returns an array of all of this element's annotation for the + * specified type if such annotations are present, else an empty + * array. The annotation may be either inherited or directly + * present on this element. This method will look through a container + * annotation (if present) if the supplied annotation type is + * repeatable. + * + *

The annotations returned by this method could contain an element + * whose value is of type {@code Class}. + * This value cannot be returned directly: information necessary to + * locate and load a class (such as the class loader to use) is + * not available, and the class might not be loadable at all. + * Attempting to read a {@code Class} object by invoking the relevant + * method on the returned annotation + * will result in a {@link MirroredTypeException}, + * from which the corresponding {@link TypeMirror} may be extracted. + * Similarly, attempting to read a {@code Class[]}-valued element + * will result in a {@link MirroredTypesException}. + * + *

+ * Note: This method is unlike others in this and related + * interfaces. It operates on runtime reflective information — + * representations of annotation types currently loaded into the + * VM — rather than on the representations defined by and used + * throughout these interfaces. Consequently, calling methods on + * the returned annotation object can throw many of the exceptions + * that can be thrown when calling methods on an annotation object + * returned by core reflection. This method is intended for + * callers that are written to operate on a known, fixed set of + * annotation types. + *
+ * + * @param the annotation type + * @param annotationType the {@code Class} object corresponding to + * the annotation type + * @return this element's annotations for the specified annotation + * type if present on this element, else an empty array + * + * @see #getAnnotationMirrors() + * @see #getAnnotation(java.lang.Class) + * @see java.lang.reflect.AnnotatedElement#getAnnotations + * @see EnumConstantNotPresentException + * @see AnnotationTypeMismatchException + * @see IncompleteAnnotationException + * @see MirroredTypeException + * @see MirroredTypesException + */ + A[] getAnnotations(Class annotationType); + /** * Returns the modifiers of this element, excluding annotations. * Implicit modifiers, such as the {@code public} and {@code static} diff --git a/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java b/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java index 34fb9328c6c..56c07bde4b8 100644 --- a/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java +++ b/langtools/src/share/classes/javax/lang/model/element/ElementVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -52,6 +52,18 @@ import javax.lang.model.util.*; * parameters, return type, etc. rather than one of the abstract * classes. * + *

Note that methods to accommodate new language constructs could + * be added in a source compatible way if they were added as + * default methods. However, default methods are only + * available on Java SE 8 and higher releases and the {@code + * javax.lang.model.*} packages bundled in Java SE 8 are required to + * also be runnable on Java SE 7. Therefore, default methods + * cannot be used when extending {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods may + * be used in subsequent revisions of the {@code javax.lang.model.*} + * packages that are only required to run on Java SE 8 and higher + * platform versions. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/type/AnnotatedType.java b/langtools/src/share/classes/javax/lang/model/type/AnnotatedType.java new file mode 100644 index 00000000000..c2a27dc6e1a --- /dev/null +++ b/langtools/src/share/classes/javax/lang/model/type/AnnotatedType.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, 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 javax.lang.model.type; + +import java.util.List; + +import javax.lang.model.element.AnnotationMirror; + +/** + * Represents an annotated type. + * + * As of the {@link javax.lang.model.SourceVersion#RELEASE_8 + * RELEASE_8} source version, annotated types can appear for all + * type uses. + * + * @author Werner Dietl + * @since 1.8 + */ +public interface AnnotatedType extends TypeMirror, + DeclaredType, TypeVariable, WildcardType, + PrimitiveType, ArrayType { + + List getAnnotations(); + TypeMirror getUnderlyingType(); +} diff --git a/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java b/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java index 7b2e63adc93..9bdccaaefb3 100644 --- a/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java +++ b/langtools/src/share/classes/javax/lang/model/type/ExecutableType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -77,6 +77,14 @@ public interface ExecutableType extends TypeMirror { */ List getParameterTypes(); + /** + * Returns the type of this executable's receiver parameter. + * + * @return the type of this executable's receiver parameter + * TODO: null if none specified or always a valid value? + */ + TypeMirror getReceiverType(); + /** * Returns the exceptions and other throwables listed in this * executable's {@code throws} clause. diff --git a/langtools/src/share/classes/javax/lang/model/type/TypeKind.java b/langtools/src/share/classes/javax/lang/model/type/TypeKind.java index 0f67a3ba7b6..1a9f11d895e 100644 --- a/langtools/src/share/classes/javax/lang/model/type/TypeKind.java +++ b/langtools/src/share/classes/javax/lang/model/type/TypeKind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -151,7 +151,14 @@ public enum TypeKind { * * @since 1.8 */ - INTERSECTION; + INTERSECTION, + + /** + * An annotated type. + * + * @since 1.8 + */ + ANNOTATED; /** * Returns {@code true} if this kind corresponds to a primitive diff --git a/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java b/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java index f95af6c87d9..2d8674d6512 100644 --- a/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java +++ b/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -52,6 +52,18 @@ import javax.lang.model.element.*; * parameters, return type, etc. rather than one of the abstract * classes. * + *

Note that methods to accommodate new language constructs could + * be added in a source compatible way if they were added as + * default methods. However, default methods are only + * available on Java SE 8 and higher releases and the {@code + * javax.lang.model.*} packages bundled in Java SE 8 are required to + * also be runnable on Java SE 7. Therefore, default methods + * cannot be used when extending {@code javax.lang.model.*} + * to cover Java SE 8 language features. However, default methods may + * be used in subsequent revisions of the {@code javax.lang.model.*} + * packages that are only required to run on Java SE 8 and higher + * platform versions. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's @@ -182,4 +194,14 @@ public interface TypeVisitor { * @since 1.8 */ R visitIntersection(IntersectionType t, P p); + + /** + * Visits an annotated type. + * + * @param t the type to visit + * @param p a visitor-specified parameter + * @return a visitor-specified result + * @since 1.8 + */ + R visitAnnotated(AnnotatedType t, P p); } diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java index 109349aa612..2d4d6b4e4b5 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java @@ -54,6 +54,15 @@ import javax.annotation.processing.SupportedSourceVersion; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java index 35a93718615..ae2438e065e 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -51,6 +51,15 @@ import javax.annotation.processing.SupportedSourceVersion; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java index c7a0f7be70f..47c25598d61 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -51,6 +51,15 @@ import javax.annotation.processing.SupportedSourceVersion; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java index 8e1d65613d5..2ce7465d151 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -53,6 +53,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java index 0e5d8daeebc..f5c87e46d0f 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -52,6 +52,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java index b4afe113fac..fb99d187f36 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractElementVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -52,6 +52,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java index c36fda3dec9..0ae91ef0977 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -49,6 +49,15 @@ import javax.lang.model.type.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's @@ -124,6 +133,23 @@ public abstract class AbstractTypeVisitor6 implements TypeVisitor { return visitUnknown(t, p); } + /** + * Visits an {@code AnnotatedType} element by calling {@code + * visit} on the underlying type. + + * @param t {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of calling {@code visit} on the underlying type + * + * @since 1.8 + * + * TODO: should xxxVisitor8 subclasses override this and call + * the defaultAction? + */ + public R visitAnnotated(AnnotatedType t, P p) { + return visit(t.getUnderlyingType(), p); + } + /** * {@inheritDoc} * diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java index 7deefe9bed7..3fe08dcc1db 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -49,6 +49,15 @@ import javax.lang.model.type.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java index 5713b24b82b..a23b6e7fc5b 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -49,6 +49,15 @@ import javax.lang.model.type.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java index f1ad3fed21f..9925955ed9a 100644 --- a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -67,6 +67,15 @@ import javax.lang.model.SourceVersion; * for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java index 25a68a909f7..ebaeb6ba67b 100644 --- a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -65,6 +65,15 @@ import static javax.lang.model.SourceVersion.*; * for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java index d5ea0f6f960..61ccc789073 100644 --- a/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/ElementKindVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -65,6 +65,15 @@ import javax.lang.model.SourceVersion; * for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java index b2995723564..1bb58b96376 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -63,6 +63,15 @@ import javax.annotation.processing.SupportedSourceVersion; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java index 2e3cfafcc70..0a442111cf7 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -58,6 +58,15 @@ import static javax.lang.model.SourceVersion.*; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java index 30823cdd584..1b84d328ca8 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -58,6 +58,15 @@ import static javax.lang.model.SourceVersion.*; * behavior for the visit method in question. When the new visitor is * introduced, all or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java index a0055f76cfe..8c7ff87fbd9 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -65,6 +65,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@code Void} * for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's methods. Use {@code Void} diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java index 5d54cff9333..b9df9c49e1c 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -62,6 +62,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@code Void} * for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's methods. Use {@code Void} diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java index 63cacd00f3c..f0cb871c99c 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleElementVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -61,6 +61,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@code Void} * for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's methods. Use {@code Void} diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java index 7fadd6de08d..5d1b3d7a309 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -64,6 +64,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java index dfb1f5d9187..66eb20aafa7 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -61,6 +61,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java index fc023d869c2..c4faae9f45e 100644 --- a/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -60,6 +60,15 @@ import static javax.lang.model.SourceVersion.*; * visit method in question. When the new visitor is introduced, all * or portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java index 9e007fe54f3..3add039d49a 100644 --- a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -63,6 +63,15 @@ import static javax.lang.model.SourceVersion.*; * method in question. When the new visitor is introduced, all or * portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java index 4bbe1d6635a..a0a0c1276a3 100644 --- a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java +++ b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -63,6 +63,15 @@ import javax.lang.model.SourceVersion; * method in question. When the new visitor is introduced, all or * portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java index 698364f791e..60b3b6125d1 100644 --- a/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/TypeKindVisitor8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -63,6 +63,15 @@ import static javax.lang.model.SourceVersion.*; * method in question. When the new visitor is introduced, all or * portions of this visitor may be deprecated. * + *

Note that adding a default implementation of a new visit method + * in a visitor class will occur instead of adding a default + * method directly in the visitor interface since a Java SE 8 + * language feature cannot be used to this version of the API since + * this version is required to be runnable on Java SE 7 + * implementations. Future versions of the API that are only required + * to run on Java SE 8 and later may take advantage of default methods + * in this situation. + * * @param the return type of this visitor's methods. Use {@link * Void} for visitors that do not need to return results. * @param

the type of the additional parameter to this visitor's diff --git a/langtools/src/share/classes/javax/lang/model/util/Types.java b/langtools/src/share/classes/javax/lang/model/util/Types.java index a53e66a53f2..7e41ddf70cd 100644 --- a/langtools/src/share/classes/javax/lang/model/util/Types.java +++ b/langtools/src/share/classes/javax/lang/model/util/Types.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -25,6 +25,9 @@ package javax.lang.model.util; +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationTypeMismatchException; +import java.lang.annotation.IncompleteAnnotationException; import java.util.List; import javax.lang.model.element.*; import javax.lang.model.type.*; @@ -298,4 +301,116 @@ public interface Types { * for the given type */ TypeMirror asMemberOf(DeclaredType containing, Element element); + + /** + * Returns the annotations targeting the type. + * + * @param type the targeted type + * @return the type annotations targeting the type + */ + List typeAnnotationsOf(TypeMirror type); + + /** + * Returns the type's annotation for the specified type if + * such an annotation is present, else {@code null}. The + * annotation has to be directly present on this + * element. + * + *

The annotation returned by this method could contain an element + * whose value is of type {@code Class}. + * This value cannot be returned directly: information necessary to + * locate and load a class (such as the class loader to use) is + * not available, and the class might not be loadable at all. + * Attempting to read a {@code Class} object by invoking the relevant + * method on the returned annotation + * will result in a {@link MirroredTypeException}, + * from which the corresponding {@link TypeMirror} may be extracted. + * Similarly, attempting to read a {@code Class[]}-valued element + * will result in a {@link MirroredTypesException}. + * + *

+ * Note: This method is unlike others in this and related + * interfaces. It operates on runtime reflective information — + * representations of annotation types currently loaded into the + * VM — rather than on the representations defined by and used + * throughout these interfaces. Consequently, calling methods on + * the returned annotation object can throw many of the exceptions + * that can be thrown when calling methods on an annotation object + * returned by core reflection. This method is intended for + * callers that are written to operate on a known, fixed set of + * annotation types. + *
+ * + * @param
the annotation type + * @param type the targeted type + * @param annotationType the {@code Class} object corresponding to + * the annotation type + * @return the type's annotation for the specified annotation + * type if present on the type, else {@code null} + * + * @see Element#getAnnotationMirrors() + * @see EnumConstantNotPresentException + * @see AnnotationTypeMismatchException + * @see IncompleteAnnotationException + * @see MirroredTypeException + * @see MirroredTypesException + */ + A typeAnnotationOf(TypeMirror type, Class annotationType); + + /** + * Returns the annotations targeting the method receiver type. + * + * @param type the targeted type + * @return the receiver type of the executable type + */ + TypeMirror receiverTypeOf(ExecutableType type); + + /** + * Returns the type's annotation for the specified executable type + * receiver if such an annotation is present, else {@code null}. The + * annotation has to be directly present on this + * element. + * + *

The annotation returned by this method could contain an element + * whose value is of type {@code Class}. + * This value cannot be returned directly: information necessary to + * locate and load a class (such as the class loader to use) is + * not available, and the class might not be loadable at all. + * Attempting to read a {@code Class} object by invoking the relevant + * method on the returned annotation + * will result in a {@link MirroredTypeException}, + * from which the corresponding {@link TypeMirror} may be extracted. + * Similarly, attempting to read a {@code Class[]}-valued element + * will result in a {@link MirroredTypesException}. + * + *

+ * Note: This method is unlike others in this and related + * interfaces. It operates on runtime reflective information — + * representations of annotation types currently loaded into the + * VM — rather than on the representations defined by and used + * throughout these interfaces. Consequently, calling methods on + * the returned annotation object can throw many of the exceptions + * that can be thrown when calling methods on an annotation object + * returned by core reflection. This method is intended for + * callers that are written to operate on a known, fixed set of + * annotation types. + *
+ * + * @param
the annotation type + * @param type the method type + * @param annotationType the {@code Class} object corresponding to + * the annotation type + * @return the type's annotation for the specified annotation + * type if present on the type, else {@code null} + * + * @see Element#getAnnotationMirrors() + * @see EnumConstantNotPresentException + * @see AnnotationTypeMismatchException + * @see IncompleteAnnotationException + * @see MirroredTypeException + * @see MirroredTypesException + */ + // TODO: no longer needed? + // A receiverTypeAnnotationOf(ExecutableType type, Class annotationType); + } diff --git a/langtools/src/share/classes/jdk/Supported.java b/langtools/src/share/classes/jdk/Supported.java new file mode 100644 index 00000000000..f5bf1c54ba6 --- /dev/null +++ b/langtools/src/share/classes/jdk/Supported.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 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; + +import java.lang.annotation.*; + +/** + * Indicates whether or not a JDK specific type or package is a + * supported part of the JDK. + * + * This annotation should only be applied to types and packages + * outside of the Java SE namespaces of {@code java.*} and + * {@code javax.*} packages. For example, certain portions of {@code + * com.sun.*} are official parts of the JDK meant to be generally + * usable while other portions of {@code com.sun.*} are not. This + * annotation type allows those portions to be easily and + * programmaticly distinguished. + * + * @since 1.8 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.PACKAGE}) +@Supported +public @interface Supported { + /** + * Whether or not this package or type is a supported part of the JDK. + */ + boolean value() default true; +} diff --git a/langtools/test/Makefile b/langtools/test/Makefile index 3a9a6d01cd1..35313f1c30d 100644 --- a/langtools/test/Makefile +++ b/langtools/test/Makefile @@ -272,6 +272,7 @@ jtreg-tests: check-jtreg FRC @mkdir -p $(JTREG_OUTPUT_DIR) JT_JAVA=$(JT_JAVA) $(JTREG) \ -J-Xmx512m \ + -vmoption:-Xmx768m \ -a -ignore:quiet -v:fail,error,nopass \ -r:$(JTREG_OUTPUT_DIR)/JTreport \ -w:$(JTREG_OUTPUT_DIR)/JTwork \ diff --git a/langtools/test/com/sun/javadoc/5093723/T5093723.java b/langtools/test/com/sun/javadoc/5093723/T5093723.java index cab8c1d53d6..4fb3f90a821 100644 --- a/langtools/test/com/sun/javadoc/5093723/T5093723.java +++ b/langtools/test/com/sun/javadoc/5093723/T5093723.java @@ -36,7 +36,7 @@ public class T5093723 extends JavadocTester { private static final String BUG_ID = "5093723"; private static final String[] ARGS = new String[] { - "-d", BUG_ID + ".out", "-source", "5", + "-d", BUG_ID + ".out", "-source", "5", "-Xdoclint:none", SRC_DIR + "/DocumentedClass.java", SRC_DIR + "/UndocumentedClass.java" }; diff --git a/langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java b/langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java index 032481764d8..75562bdee08 100644 --- a/langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java +++ b/langtools/test/com/sun/javadoc/DocRootSlash/DocRootSlash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -60,6 +60,7 @@ public class DocRootSlash String srcdir = System.getProperty("test.src", "."); runJavadoc(new String[] {"-d", TMPDIR_STRING1, + "-Xdoclint:none", "-overview", (srcdir + FS + "overview.html"), "-header", "{@docroot} {@docRoot}", "-sourcepath", srcdir, diff --git a/langtools/test/com/sun/javadoc/testAnnotationOptional/TestAnnotationOptional.java b/langtools/test/com/sun/javadoc/testAnnotationOptional/TestAnnotationOptional.java new file mode 100644 index 00000000000..ecd96852281 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testAnnotationOptional/TestAnnotationOptional.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 Make sure that annotations types with optional elements has + * element headers + * @author Mahmood Ali + * @library ../lib/ + * @build JavadocTester + * @build TestAnnotationOptional + * @run main TestAnnotationOptional + */ + +public class TestAnnotationOptional extends JavadocTester { + + //Test information. + private static final String BUG_ID = "NO_BUG_ID_YET"; + + //Javadoc arguments. + private static final String[] ARGS = new String[] { + "-d", BUG_ID, "-sourcepath", SRC_DIR, "-source", "1.5", "pkg" + }; + + //Input for string search tests. + private static final String[][] TEST = { + {BUG_ID + FS + "pkg" + FS + "AnnotationOptional.html", + "" + } + }; + + private static final String[][] NEGATED_TEST = NO_TEST; + + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestAnnotationOptional tester = new TestAnnotationOptional(); + run(tester, ARGS, TEST, NEGATED_TEST); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/testAnnotationOptional/pkg/AnnotationOptional.java b/langtools/test/com/sun/javadoc/testAnnotationOptional/pkg/AnnotationOptional.java new file mode 100644 index 00000000000..7004c1d4344 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testAnnotationOptional/pkg/AnnotationOptional.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 pkg; + +import java.lang.annotation.*; + +/** + * This is just a test annotation type with optional value element. + * + * @author Mahmood Ali + * @since 1.5 + */ +@Documented public @interface AnnotationOptional { + String value() default ""; +} diff --git a/langtools/test/com/sun/javadoc/testBadSourceFile/TestBadSourceFile.java b/langtools/test/com/sun/javadoc/testBadSourceFile/TestBadSourceFile.java index 9f928543957..266aafdde1f 100644 --- a/langtools/test/com/sun/javadoc/testBadSourceFile/TestBadSourceFile.java +++ b/langtools/test/com/sun/javadoc/testBadSourceFile/TestBadSourceFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ public class TestBadSourceFile extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, SRC_DIR + FS + "C2.java" + "-Xdoclint:none", "-d", BUG_ID, SRC_DIR + FS + "C2.java" }; //Input for string search tests. diff --git a/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java index 508175a1949..7c403e5b5b0 100644 --- a/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java +++ b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -222,19 +222,19 @@ public class TestHtmlDefinitionListTag extends JavadocTester { private static final String[] ARGS1 = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS2 = new String[] { - "-d", BUG_ID, "-nocomment", "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", BUG_ID, "-nocomment", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS3 = new String[] { - "-d", BUG_ID, "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", BUG_ID, "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; private static final String[] ARGS4 = new String[] { - "-d", BUG_ID, "-nocomment", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; + "-Xdoclint:none", "-d", BUG_ID, "-nocomment", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; /** * The entry point of the test. diff --git a/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java b/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java index 0ad0d86e84e..cc6694594e4 100644 --- a/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java +++ b/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ public class TestNewLanguageFeatures extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-use", "-source", "1.5", "-sourcepath", SRC_DIR, "pkg", "pkg1", "pkg2" + "-Xdoclint:none", "-d", BUG_ID, "-use", "-source", "1.5", "-sourcepath", SRC_DIR, "pkg", "pkg1", "pkg2" }; //Input for string search tests. diff --git a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java index 8499ffb5e8b..a0208e201b3 100644 --- a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java +++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContaineeSynthDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,6 @@ import java.lang.annotation.*; * @author Bhavesh Patel */ @Documented -@ContainedBy(ContainerSynthDoc.class) +@Repeatable(ContainerSynthDoc.class) public @interface ContaineeSynthDoc { } diff --git a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java index 950b923d357..bdf86ee8537 100644 --- a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java +++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg/ContainerSynthDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,7 +32,6 @@ import java.lang.annotation.*; * @author Bhavesh Patel */ @Documented -@ContainerFor(ContaineeSynthDoc.class) public @interface ContainerSynthDoc { ContaineeSynthDoc[] value(); diff --git a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java index 15722e3324e..a3211095282 100644 --- a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java +++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContaineeSynthDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,6 @@ import java.lang.annotation.*; * @author Bhavesh Patel */ @Documented -@ContainedBy(ContainerSynthNotDoc.class) +@Repeatable(ContainerSynthNotDoc.class) public @interface ContaineeSynthDoc { } diff --git a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java index fbdfc272b18..247dd1edd2e 100644 --- a/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java +++ b/langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -31,7 +31,6 @@ import java.lang.annotation.*; * * @author Bhavesh Patel */ -@ContainerFor(ContaineeSynthDoc.class) public @interface ContainerSynthNotDoc { ContaineeSynthDoc[] value(); diff --git a/langtools/test/com/sun/javadoc/testReturnTag/TestReturnTag.java b/langtools/test/com/sun/javadoc/testReturnTag/TestReturnTag.java index eab8f02acd6..b7319746af3 100644 --- a/langtools/test/com/sun/javadoc/testReturnTag/TestReturnTag.java +++ b/langtools/test/com/sun/javadoc/testReturnTag/TestReturnTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ public class TestReturnTag extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, SRC_DIR + FS + "TestReturnTag.java" + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, SRC_DIR + FS + "TestReturnTag.java" }; //Input for string search tests. diff --git a/langtools/test/com/sun/javadoc/testTagInheritence/TestTagInheritence.java b/langtools/test/com/sun/javadoc/testTagInheritence/TestTagInheritence.java index ca6f4c0f108..194d10ef118 100644 --- a/langtools/test/com/sun/javadoc/testTagInheritence/TestTagInheritence.java +++ b/langtools/test/com/sun/javadoc/testTagInheritence/TestTagInheritence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -36,7 +36,7 @@ public class TestTagInheritence extends JavadocTester { private static final String BUG_ID = "4496223-4496270-4618686-4720974-4812240-6253614-6253604"; private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg", "firstSentence", "firstSentence2" + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg", "firstSentence", "firstSentence2" }; /** diff --git a/langtools/test/com/sun/javadoc/testTagMisuse/TestTagMisuse.java b/langtools/test/com/sun/javadoc/testTagMisuse/TestTagMisuse.java index b80c4ca3141..d5f67301b60 100644 --- a/langtools/test/com/sun/javadoc/testTagMisuse/TestTagMisuse.java +++ b/langtools/test/com/sun/javadoc/testTagMisuse/TestTagMisuse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -42,7 +42,7 @@ public class TestTagMisuse extends JavadocTester { }; private static final String[][] NEGATED_TEST = NO_TEST; private static final String[] ARGS = new String[] { - "-d", BUG_ID, SRC_DIR + FS + "TestTagMisuse.java" + "-Xdoclint:none", "-d", BUG_ID, SRC_DIR + FS + "TestTagMisuse.java" }; /** diff --git a/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java b/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java index 08780aa6acb..f53e6f4f1a5 100644 --- a/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java +++ b/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ public class TestValueTag extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "-tag", "todo", "pkg1", "pkg2" }; diff --git a/langtools/test/com/sun/javadoc/testWarnBadParamNames/TestWarnBadParamNames.java b/langtools/test/com/sun/javadoc/testWarnBadParamNames/TestWarnBadParamNames.java index de23e99862f..1d58351cff0 100644 --- a/langtools/test/com/sun/javadoc/testWarnBadParamNames/TestWarnBadParamNames.java +++ b/langtools/test/com/sun/javadoc/testWarnBadParamNames/TestWarnBadParamNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -43,7 +43,7 @@ public class TestWarnBadParamNames extends JavadocTester { }; private static final String[][] NEGATED_TEST = NO_TEST; private static final String[] ARGS = new String[] { - "-d", BUG_ID, SRC_DIR + FS + "C.java" + "-Xdoclint:none", "-d", BUG_ID, SRC_DIR + FS + "C.java" }; /** diff --git a/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java b/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java index bf21f3f0d8f..d5f697a213e 100644 --- a/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java +++ b/langtools/test/com/sun/javadoc/testWarnings/TestWarnings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -43,11 +43,11 @@ public class TestWarnings extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg" + "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg" }; private static final String[] ARGS2 = new String[] { - "-d", BUG_ID, "-private", "-sourcepath", SRC_DIR, "pkg" + "-Xdoclint:none", "-d", BUG_ID, "-private", "-sourcepath", SRC_DIR, "pkg" }; //Input for string search tests. diff --git a/langtools/test/com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java new file mode 100644 index 00000000000..dc8d10b1146 --- /dev/null +++ b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8006735 + * @ignore + * @summary Smoke test for ensuring that annotations are emited to javadoc + * + * @author Mahmood Ali + * @library ../../lib/ + * @build JavadocTester + * @build TestSmoke + * @run main TestSmoke + */ + +public class TestSmoke extends JavadocTester { + + //Test information. + private static final String BUG_ID = "NOT_SPECIFIED_YET"; + + //Javadoc arguments. + private static final String[] ARGS = new String[] { + "-d", BUG_ID, "-private", "-sourcepath", SRC_DIR, "pkg" + }; + + //Input for string search tests. + private static final String[][] TEST = { + {BUG_ID + FS + "pkg" + FS + "T0x1C.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x1D.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x0D.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x06.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x0B.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x0F.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x20.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x22.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x10.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x10A.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x12.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x11.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x13.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x15.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x14.html", "@DA"}, + {BUG_ID + FS + "pkg" + FS + "T0x16.html", "@DA"} + }; + + private static final String[][] NEGATED_TEST = { + {BUG_ID + FS + "pkg" + FS + "T0x1C.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x1D.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x00.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x01.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x02.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x04.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x08.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x0D.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x06.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x0B.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x0F.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x20.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x22.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x10.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x10A.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x12.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x11.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x13.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x15.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x14.html", "@A"}, + {BUG_ID + FS + "pkg" + FS + "T0x16.html", "@A"} + }; + + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestSmoke tester = new TestSmoke(); + run(tester, ARGS, TEST, NEGATED_TEST); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/typeAnnotations/smoke/pkg/TargetTypes.java b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/pkg/TargetTypes.java new file mode 100644 index 00000000000..24c93e3ba08 --- /dev/null +++ b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/pkg/TargetTypes.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 pkg; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.util.*; +import java.io.*; + +/* + * @summary compiler accepts all values + * @author Mahmood Ali + * @author Yuri Gaevsky + */ + +@Target({TYPE_USE}) +@Retention(RetentionPolicy.RUNTIME) +@interface A {} + +@Target({TYPE_USE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@interface DA {} + +/** wildcard bound */ +class T0x1C { + void m0x1C(List lst) {} +} + +/** wildcard bound generic/array */ +class T0x1D { + void m0x1D(List> lst) {} +} + +/** typecast */ +class T0x00 { + void m0x00(Long l1) { + Object l2 = (@A @DA Long) l1; + } +} + +/** typecast generic/array */ +class T0x01 { + void m0x01(List list) { + List l = (List<@A @DA T>) list; + } +} + +/** instanceof */ +class T0x02 { + boolean m0x02(String s) { + return (s instanceof @A @DA String); + } +} + +/** object creation (new) */ +class T0x04 { + void m0x04() { + new @A @DA ArrayList(); + } +} + +/** local variable */ +class T0x08 { + void m0x08() { + @A @DA String s = null; + } +} + +/** method parameter generic/array */ +class T0x0D { + void m0x0D(HashMap<@A @DA Object, List<@A @DA List<@A @DA Class>>> s1) {} +} + +/** method receiver */ +class T0x06 { + void m0x06(@A @DA T0x06 this) {} +} + +/** method return type generic/array */ +class T0x0B { + Class<@A @DA Object> m0x0B() { return null; } +} + +/** field generic/array */ +class T0x0F { + HashMap<@A @DA Object, @A @DA Object> c1; +} + +/** method type parameter */ +class T0x20 { + <@A @DA T, @A @DA U> void m0x20() {} +} + +/** class type parameter */ +class T0x22<@A @DA T, @A @DA U> { +} + +/** class type parameter bound */ +class T0x10 { +} + +class T0x10A { +} + +/** method type parameter bound */ +class T0x12 { + void m0x12() {} +} + +/** class type parameter bound generic/array */ +class T0x11> { +} + +/** method type parameter bound generic/array */ +class T0x13 { + static > T m0x13() { + return null; + } +} + +/** class extends/implements generic/array */ +class T0x15 extends ArrayList<@A @DA T> { +} + +/** type test (instanceof) generic/array */ +class T0x03 { + void m0x03(T typeObj, Object obj) { + boolean ok = obj instanceof String @A @DA []; + } +} + +/** object creation (new) generic/array */ +class T0x05 { + void m0x05() { + new ArrayList<@A @DA T>(); + } +} + +/** local variable generic/array */ +class T0x09 { + void g() { + List<@A @DA String> l = null; + } + + void a() { + String @A @DA [] as = null; + } +} + +/** type argument in constructor call generic/array */ +class T0x19 { + T0x19() {} + + void g() { + new > T0x19(); + } +} + +/** type argument in method call generic/array */ +class T0x1B { + void m0x1B() { + Collections.emptyList(); + } +} + +/** type argument in constructor call */ +class T0x18 { + T0x18() {} + + void m() { + new <@A @DA Integer> T0x18(); + } +} + +/** type argument in method call */ +class T0x1A { + public static T m() { return null; } + static void m0x1A() { + T0x1A.<@A @DA Integer, @A @DA Short>m(); + } +} + +/** class extends/implements */ +class T0x14 extends @A @DA Thread implements @A @DA Serializable, @A @DA Cloneable { +} + +/** exception type in throws */ +class T0x16 { + void m0x16() throws @A @DA Exception {} +} diff --git a/langtools/test/tools/doclint/AnchorTest.java b/langtools/test/tools/doclint/AnchorTest.java new file mode 100644 index 00000000000..08e19031b4a --- /dev/null +++ b/langtools/test/tools/doclint/AnchorTest.java @@ -0,0 +1,93 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8004832 + * @summary Add new doclint package + * @build DocLintTester + * @run main DocLintTester -ref AnchorTest.out AnchorTest.java + */ + +/** */ +public class AnchorTest { + // tests for + + /** + * + */ + public void a_name_foo() { } + + /** + * + */ + public void a_name_already_defined() { } + + /** + * + */ + public void a_name_empty() { } + + /** + * + */ + public void a_name_invalid() { } + + /** + * + */ + public void a_name_missing() { } + + // tests for + + /** + * + */ + public void a_id_foo() { } + + /** + * + */ + public void a_id_already_defined() { } + + /** + * + */ + public void a_id_empty() { } + + /** + * + */ + public void a_id_invalid() { } + + /** + * + */ + public void a_id_missing() { } + + // tests for id=value on non- tags + + /** + *

text

+ */ + public void p_id_foo() { } + + /** + *

text

+ */ + public void p_id_already_defined() { } + + /** + *

text

+ */ + public void p_id_empty() { } + + /** + *

text

+ */ + public void p_id_invalid() { } + + /** + *

text

+ */ + public void p_id_missing() { } + + +} diff --git a/langtools/test/tools/doclint/AnchorTest.out b/langtools/test/tools/doclint/AnchorTest.out new file mode 100644 index 00000000000..562be5ba96c --- /dev/null +++ b/langtools/test/tools/doclint/AnchorTest.out @@ -0,0 +1,37 @@ +AnchorTest.java:19: error: anchor already defined: foo + *
+ ^ +AnchorTest.java:24: error: invalid name for anchor: "" + * + ^ +AnchorTest.java:29: error: invalid name for anchor: "123" + * + ^ +AnchorTest.java:34: error: no value given for anchor + * + ^ +AnchorTest.java:46: error: anchor already defined: foo + * + ^ +AnchorTest.java:51: error: invalid name for anchor: "" + * + ^ +AnchorTest.java:56: error: invalid name for anchor: "123" + * + ^ +AnchorTest.java:61: error: no value given for anchor + * + ^ +AnchorTest.java:73: error: anchor already defined: foo + *

text

+ ^ +AnchorTest.java:78: error: invalid name for anchor: "" + *

text

+ ^ +AnchorTest.java:83: error: invalid name for anchor: "123" + *

text

+ ^ +AnchorTest.java:88: error: no value given for anchor + *

text

+ ^ +12 errors diff --git a/langtools/test/tools/doclint/CoverageExtras.java b/langtools/test/tools/doclint/CoverageExtras.java new file mode 100644 index 00000000000..e083d70cda6 --- /dev/null +++ b/langtools/test/tools/doclint/CoverageExtras.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 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. + */ + +/** + * @test + * @bug 8006263 + * @summary Supplementary test cases needed for doclint + */ + +import com.sun.tools.doclint.Checker; +import com.sun.tools.doclint.Entity; +import com.sun.tools.doclint.HtmlTag; +import com.sun.tools.doclint.Messages; +import java.util.Objects; + +public class CoverageExtras { + public static void main(String... args) { + new CoverageExtras().run(); + } + + void run() { + check(HtmlTag.A, HtmlTag.valueOf("A"), HtmlTag.values()); + check(HtmlTag.Attr.ABBR, HtmlTag.Attr.valueOf("ABBR"), HtmlTag.Attr.values()); + check(HtmlTag.AttrKind.INVALID, HtmlTag.AttrKind.valueOf("INVALID"), HtmlTag.AttrKind.values()); + check(HtmlTag.BlockType.BLOCK, HtmlTag.BlockType.valueOf("BLOCK"), HtmlTag.BlockType.values()); + check(HtmlTag.EndKind.NONE, HtmlTag.EndKind.valueOf("NONE"), HtmlTag.EndKind.values()); + check(HtmlTag.Flag.EXPECT_CONTENT, HtmlTag.Flag.valueOf("EXPECT_CONTENT"), HtmlTag.Flag.values()); + + check(Checker.Flag.TABLE_HAS_CAPTION, Checker.Flag.valueOf("TABLE_HAS_CAPTION"), Checker.Flag.values()); + + check(Entity.nbsp, Entity.valueOf("nbsp"), Entity.values()); + + check(Messages.Group.ACCESSIBILITY, Messages.Group.valueOf("ACCESSIBILITY"), Messages.Group.values()); + } + + > void check(T expect, T value, T[] values) { + if (!Objects.equals(expect, value)) { + error("Mismatch: '" + expect + "', '" + value + "'"); + } + if (!Objects.equals(expect, values[0])) { + error("Mismatch: '" + expect + "', '" + values[0] + "'"); + } + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; +} diff --git a/langtools/test/tools/doclint/DocLintTester.java b/langtools/test/tools/doclint/DocLintTester.java index 53e26b352f0..848e284b57d 100644 --- a/langtools/test/tools/doclint/DocLintTester.java +++ b/langtools/test/tools/doclint/DocLintTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; import com.sun.tools.doclint.DocLint; +import com.sun.tools.doclint.DocLint.BadArgs; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -45,6 +46,7 @@ public class DocLintTester { public void run(String... args) throws Exception { String testSrc = System.getProperty("test.src"); + boolean badArgs = false; File refFile = null; List opts = new ArrayList(); List files = new ArrayList(); @@ -52,19 +54,25 @@ public class DocLintTester { String arg = args[i]; if (arg.equals("-ref")) { refFile = new File(testSrc, args[++i]); + } else if (arg.equals("-badargs")) { + badArgs = true; } else if (arg.startsWith("-Xmsgs")) { opts.add(arg); + } else if (arg.startsWith("-")) { + opts.add(arg); + if (i < args.length - 1 && !args[i+1].startsWith("-")) + opts.add(args[++i]); } else files.add(new File(testSrc, arg)); } - check(opts, files, refFile); + check(opts, files, badArgs, refFile); if (errors > 0) throw new Exception(errors + " errors occurred"); } - void check(List opts, List files, File refFile) throws Exception { + void check(List opts, List files, boolean expectBadArgs, File refFile) throws Exception { List args = new ArrayList(); args.addAll(opts); for (File file: files) @@ -72,7 +80,14 @@ public class DocLintTester { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - new DocLint().run(pw, args.toArray(new String[args.size()])); + try { + new DocLint().run(pw, args.toArray(new String[args.size()])); + if (expectBadArgs) + error("expected exception not thrown"); + } catch (BadArgs e) { + if (!expectBadArgs) + error("unexpected exception caught: " + e); + } pw.flush(); String out = normalizeNewlines(removeFileNames(sw.toString())).trim(); if (out != null) diff --git a/langtools/test/tools/doclint/EndTagsTest.java b/langtools/test/tools/doclint/EndTagsTest.java new file mode 100644 index 00000000000..154f516324a --- /dev/null +++ b/langtools/test/tools/doclint/EndTagsTest.java @@ -0,0 +1,39 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006236 + * @summary doclint: structural issue hidden + * @build DocLintTester + * @run main DocLintTester -Xmsgs:-html EndTagsTest.java + * @run main DocLintTester -ref EndTagsTest.out EndTagsTest.java + */ + +/** */ +public class EndTagsTest { + /**

text image

*/ + public void valid_all() { } + + /**

text image */ + public void valid_omit_optional_close() { } + + /** */ + public void invalid_missing_start() { } + + /**

*/ + public void invalid_missing_start_2() { } + + /**

text

*/ + public void invalid_missing_start_3() { } + + /** image */ + public void invalid_end() { } + + /** */ + public void unknown_start_end() { } + + /** */ + public void unknown_start() { } + + /** */ + public void unknown_end() { } +} + diff --git a/langtools/test/tools/doclint/EndTagsTest.out b/langtools/test/tools/doclint/EndTagsTest.out new file mode 100644 index 00000000000..61af632535c --- /dev/null +++ b/langtools/test/tools/doclint/EndTagsTest.out @@ -0,0 +1,25 @@ +EndTagsTest.java:18: error: unexpected end tag: + /** */ + ^ +EndTagsTest.java:21: error: unexpected end tag: + /**

*/ + ^ +EndTagsTest.java:24: error: unexpected end tag: + /**

text

*/ + ^ +EndTagsTest.java:27: error: invalid end tag: + /** image */ + ^ +EndTagsTest.java:30: error: unknown tag: invalid + /** */ + ^ +EndTagsTest.java:30: error: unknown tag: invalid + /** */ + ^ +EndTagsTest.java:33: error: unknown tag: invalid + /** */ + ^ +EndTagsTest.java:36: error: unknown tag: invalid + /** */ + ^ +8 errors diff --git a/langtools/test/tools/doclint/EndWithIdentifierTest.java b/langtools/test/tools/doclint/EndWithIdentifierTest.java new file mode 100644 index 00000000000..afd20a3353c --- /dev/null +++ b/langtools/test/tools/doclint/EndWithIdentifierTest.java @@ -0,0 +1,32 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8007096 + * @summary DocLint parsing problems with some comments + * @build DocLintTester + * @run main DocLintTester -Xmsgs:-html EndWithIdentifierTest.java + * @run main DocLintTester -Xmsgs -ref EndWithIdentifierTest.out EndWithIdentifierTest.java + * @author jlahoda + */ + +/**@deprecated*/ +public class EndWithIdentifierTest { + + /**{@link*/ + private void unfinishedInlineTagName() {} + + /**@see List*/ + private void endsWithIdentifier() {} + + /**&*/ + private void entityName() {} + + /** */ public void end_unexpected() { } + + /** + *
    text
  • ...
+ */ + public void text_not_allowed() { } + + /** + *
    text
  • ...
+ */ + public void inline_not_allowed() { } + + } diff --git a/langtools/test/tools/doclint/HtmlTagsTest.out b/langtools/test/tools/doclint/HtmlTagsTest.out index a9ea7d8a15d..19be7237728 100644 --- a/langtools/test/tools/doclint/HtmlTagsTest.out +++ b/langtools/test/tools/doclint/HtmlTagsTest.out @@ -34,5 +34,11 @@ HtmlTagsTest.java:54: error: unexpected end tag: HtmlTagsTest.java:54: warning: empty tag * ^ -11 errors +HtmlTagsTest.java:59: error: text not allowed in
    element + *
      text
    • ...
    + ^ +HtmlTagsTest.java:64: error: tag not allowed here: + *
      text
    • ...
    + ^ +13 errors 1 warning diff --git a/langtools/test/tools/doclint/LiteralTest.java b/langtools/test/tools/doclint/LiteralTest.java new file mode 100644 index 00000000000..008246edee6 --- /dev/null +++ b/langtools/test/tools/doclint/LiteralTest.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006228 + * @summary Doclint doesn't detect {@code nested inline} + * @build DocLintTester + * @run main DocLintTester -ref LiteralTest.out LiteralTest.java + */ + +/** */ +public class LiteralTest { + /** abc {@literal < & > } def */ + public void ok_literal_in_code() { } + + /** abc {@code < & > } def */ + public void bad_code_in_code() { } +} diff --git a/langtools/test/tools/doclint/LiteralTest.out b/langtools/test/tools/doclint/LiteralTest.out new file mode 100644 index 00000000000..4cb41d9d7bb --- /dev/null +++ b/langtools/test/tools/doclint/LiteralTest.out @@ -0,0 +1,4 @@ +LiteralTest.java:14: warning: {@code} within + /** abc {@code < & > } def */ + ^ +1 warning diff --git a/langtools/test/tools/doclint/UnfinishedInlineTagTest.java b/langtools/test/tools/doclint/UnfinishedInlineTagTest.java new file mode 100644 index 00000000000..7b4345554d8 --- /dev/null +++ b/langtools/test/tools/doclint/UnfinishedInlineTagTest.java @@ -0,0 +1,17 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8007096 + * @summary DocLint parsing problems with some comments + * @build DocLintTester + * @run main DocLintTester -Xmsgs:-html UnfinishedInlineTagTest.java + * @run main DocLintTester -Xmsgs -ref UnfinishedInlineTagTest.out UnfinishedInlineTagTest.java + * @author jlahoda + */ + +import java.util.List; + +/**{@link List + */ +public class UnfinishedInlineTagTest { +} + diff --git a/langtools/test/tools/doclint/UnfinishedInlineTagTest.out b/langtools/test/tools/doclint/UnfinishedInlineTagTest.out new file mode 100644 index 00000000000..eb70f3a66b9 --- /dev/null +++ b/langtools/test/tools/doclint/UnfinishedInlineTagTest.out @@ -0,0 +1,5 @@ +UnfinishedInlineTagTest.java:14: error: unterminated inline tag + */ +^ +1 error + diff --git a/langtools/test/tools/doclint/html/AAA.java b/langtools/test/tools/doclint/html/AAA.java new file mode 100644 index 00000000000..3880733edc9 --- /dev/null +++ b/langtools/test/tools/doclint/html/AAA.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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. + */ + +/** + * @test + * @bug 8006728 + * @summary temporarily workaround jtreg problems for doclint tests in othervm + */ + +// dummy test/class to be compiled before other tests in this directory +// see JDK-8006730 +public class AAA { + public static void main(String... args) { } +} + diff --git a/langtools/test/tools/doclint/html/BlockTagsTest.java b/langtools/test/tools/doclint/html/BlockTagsTest.java new file mode 100644 index 00000000000..aaddc068de5 --- /dev/null +++ b/langtools/test/tools/doclint/html/BlockTagsTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006251 + * @summary test block tags + * @library .. + * @build DocLintTester + * @run main DocLintTester -Xmsgs BlockTagsTest.java + */ + +/** */ +public class BlockTagsTest { + /** + *
    abc
    + *
    abc
    + *
    abc
    + *
    abc
    def
    + *
    abc
    + *

    abc

    + *

    abc

    + *

    abc

    + *

    abc

    + *
    abc
    + *
    abc
    + *
    + *
  • abc
  • + * + *
    1. abc
    + *

    abc

    + *
     abc 
    + *
    + *
    • abc
    + */ + public void supportedTags() { } +} diff --git a/langtools/test/tools/doclint/html/EntitiesTest.java b/langtools/test/tools/doclint/html/EntitiesTest.java new file mode 100644 index 00000000000..3c05f4207a0 --- /dev/null +++ b/langtools/test/tools/doclint/html/EntitiesTest.java @@ -0,0 +1,317 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006263 + * @summary Supplementary test cases needed for doclint + * @library .. + * @build DocLintTester + * @run main DocLintTester -Xmsgs:-html EntitiesTest.java + * @run main DocLintTester -Xmsgs:html -ref EntitiesTest.out EntitiesTest.java + */ + +/** */ +class EntitiesTest { + + /** + * + * ࡎ ࡎ ࡎ + */ + void range_test() { } + + /** + *     + * ¡ ¡ + * ¢ ¢ + * £ £ + * ¤ ¤ + * ¥ ¥ + * ¦ ¦ + * § § + * ¨ ¨ + * © © + * ª ª + * « « + * ¬ ¬ + * ­ ­ + * ® ® + * ¯ ¯ + * ° ° + * ± ± + * ² ² + * ³ ³ + * ´ ´ + * µ µ + * ¶ ¶ + * · · + * ¸ ¸ + * ¹ ¹ + * º º + * » » + * ¼ ¼ + * ½ ½ + * ¾ ¾ + * ¿ ¿ + * À À + * Á Á + *   + * à à + * Ä Ä + * Å Å + * Æ Æ + * Ç Ç + * È È + * É É + * Ê Ê + * Ë Ë + * Ì Ì + * Í Í + * Î Î + * Ï Ï + * Ð Ð + * Ñ Ñ + * Ò Ò + * Ó Ó + * Ô Ô + * Õ Õ + * Ö Ö + * × × + * Ø Ø + * Ù Ù + * Ú Ú + * Û Û + * Ü Ü + * Ý Ý + * Þ Þ + * ß ß + * à à + * á á + * â â + * ã ã + * ä ä + * å å + * æ æ + * ç ç + * è è + * é é + * ê ê + * ë ë + * ì ì + * í í + * î î + * ï ï + * ð ð + * ñ ñ + * ò ò + * ó ó + * ô ô + * õ õ + * ö ö + * ÷ ÷ + * ø ø + * ù ù + * ú ú + * û û + * ü ü + * ý ý + * þ þ + * ÿ ÿ + * ƒ ƒ + * Α Α + * Β Β + * Γ Γ + * Δ Δ + * Ε Ε + * Ζ Ζ + * Η Η + * Θ Θ + * Ι Ι + * Κ Κ + * Λ Λ + * Μ Μ + * Ν Ν + * Ξ Ξ + * Ο Ο + * Π Π + * Ρ Ρ + * Σ Σ + * Τ Τ + * Υ Υ + * Φ Φ + * Χ Χ + * Ψ Ψ + * Ω Ω + * α α + * β β + * γ γ + * δ δ + * ε ε + * ζ ζ + * η η + * θ θ + * ι ι + * κ κ + * λ λ + * μ μ + * ν ν + * ξ ξ + * ο ο + * π π + * ρ ρ + * ς ς + * σ σ + * τ τ + * υ υ + * φ φ + * χ χ + * ψ ψ + * ω ω + * ϑ ϑ + * ϒ ϒ + * ϖ ϖ + * • • + * … … + * ′ ′ + * ″ ″ + * ‾ ‾ + * ⁄ ⁄ + * ℘ ℘ + * ℑ ℑ + * ℜ ℜ + * ™ ™ + * ℵ ℵ + * ← ← + * ↑ ↑ + * → → + * ↓ ↓ + * ↔ ↔ + * ↵ ↵ + * ⇐ ⇐ + * ⇑ ⇑ + * ⇒ ⇒ + * ⇓ ⇓ + * ⇔ ⇔ + * ∀ ∀ + * ∂ ∂ + * ∃ ∃ + * ∅ ∅ + * ∇ ∇ + * ∈ ∈ + * ∉ ∉ + * ∋ ∋ + * ∏ ∏ + * ∑ ∑ + * − − + * ∗ ∗ + * √ √ + * ∝ ∝ + * ∞ ∞ + * ∠ ∠ + * ∧ ∧ + * ∨ ∨ + * ∩ ∩ + * ∪ ∪ + * &_int; ∫ + * ∴ ∴ + * ∼ ∼ + * ≅ ≅ + * ≈ ≈ + * ≠ ≠ + * ≡ ≡ + * ≤ ≤ + * ≥ ≥ + * ⊂ ⊂ + * ⊃ ⊃ + * ⊄ ⊄ + * ⊆ ⊆ + * ⊇ ⊇ + * ⊕ ⊕ + * ⊗ ⊗ + * ⊥ ⊥ + * ⋅ ⋅ + * ⌈ ⌈ + * ⌉ ⌉ + * ⌊ ⌊ + * ⌋ ⌋ + * ⟨ 〈 + * ⟩ 〉 + * ◊ ◊ + * ♠ ♠ + * ♣ ♣ + * ♥ ♥ + * ♦ ♦ + * " " + * & & + * < < + * > > + * Œ Œ + * œ œ + * Š Š + * š š + * Ÿ Ÿ + * ˆ ˆ + * ˜ ˜ + *     + *     + *     + * ‌ ‌ + * ‍ ‍ + * ‎ ‎ + * ‏ ‏ + * – – + * — — + * ‘ ‘ + * ’ ’ + * ‚ ‚ + * “ “ + * ” ” + * „ „ + * † † + * ‡ ‡ + * ‰ ‰ + * ‹ ‹ + * › › + * € € + */ + void symbolic_entities() { } + + /** + * &bad; + */ + void bad_name() { } + + /** + *  + * ࡏ + */ + void out_of_range() { } + + /** + * ― + * ⌫ + * ￿ + */ + void sparse_negative() { } +} + diff --git a/langtools/test/tools/doclint/html/EntitiesTest.out b/langtools/test/tools/doclint/html/EntitiesTest.out new file mode 100644 index 00000000000..98a20d454e0 --- /dev/null +++ b/langtools/test/tools/doclint/html/EntitiesTest.out @@ -0,0 +1,19 @@ +EntitiesTest.java:300: error: invalid entity &bad; + * &bad; + ^ +EntitiesTest.java:305: error: invalid entity  + *  + ^ +EntitiesTest.java:306: error: invalid entity ࡏ + * ࡏ + ^ +EntitiesTest.java:311: error: invalid entity ― + * ― + ^ +EntitiesTest.java:312: error: invalid entity ⌫ + * ⌫ + ^ +EntitiesTest.java:313: error: invalid entity ￿ + * ￿ + ^ +6 errors diff --git a/langtools/test/tools/doclint/html/InlineTagsTest.java b/langtools/test/tools/doclint/html/InlineTagsTest.java new file mode 100644 index 00000000000..4835b36a9a0 --- /dev/null +++ b/langtools/test/tools/doclint/html/InlineTagsTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006251 + * @summary test inline tags + * @library .. + * @build DocLintTester + * @run main DocLintTester -Xmsgs InlineTagsTest.java + */ + +/** */ +public class InlineTagsTest { + /** + * abc + * abc + * abc + *
    + * abc + * abc + * abc + * abc + * abc + * image + * abc + * abc + * abc + * abc + * abc + * abc + * abc + * abc + */ + public void supportedTags() { } +} + diff --git a/langtools/test/tools/doclint/html/ListTagsTest.java b/langtools/test/tools/doclint/html/ListTagsTest.java new file mode 100644 index 00000000000..c7d2080611c --- /dev/null +++ b/langtools/test/tools/doclint/html/ListTagsTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006251 + * @summary test list tags + * @library .. + * @build DocLintTester + * @run main DocLintTester -Xmsgs ListTagsTest.java + */ + +/** */ +public class ListTagsTest { + /** + *
    abc
    def
    + *
    1. abc
    + *
    • abc
    + */ + public void supportedTags() { } +} diff --git a/langtools/test/tools/doclint/html/OtherTagsTest.java b/langtools/test/tools/doclint/html/OtherTagsTest.java new file mode 100644 index 00000000000..ce6af8246c7 --- /dev/null +++ b/langtools/test/tools/doclint/html/OtherTagsTest.java @@ -0,0 +1,24 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006251 + * @summary test other tags + * @library .. + * @build DocLintTester + * @run main DocLintTester -Xmsgs -ref OtherTagsTest.out OtherTagsTest.java + */ + +/** */ +public class OtherTagsTest { + /** + *

    abc + * + * + * + * + * + * + * + * + */ + public void knownInvalidTags() { } +} diff --git a/langtools/test/tools/doclint/html/OtherTagsTest.out b/langtools/test/tools/doclint/html/OtherTagsTest.out new file mode 100644 index 00000000000..0ead88e77a5 --- /dev/null +++ b/langtools/test/tools/doclint/html/OtherTagsTest.out @@ -0,0 +1,28 @@ +OtherTagsTest.java:13: error: element not allowed in documentation comments: + *

    abc + ^ +OtherTagsTest.java:14: error: element not allowed in documentation comments: + * + ^ +OtherTagsTest.java:15: error: element not allowed in documentation comments: + * + ^ +OtherTagsTest.java:16: error: element not allowed in documentation comments: + * + ^ +OtherTagsTest.java:17: error: element not allowed in documentation comments: + * + ^ +OtherTagsTest.java:18: error: element not allowed in documentation comments: + * + ^ +OtherTagsTest.java:19: error: element not allowed in documentation comments: + * <noframes> + ^ +OtherTagsTest.java:20: error: element not allowed in documentation comments: + ^ +OtherTagsTest.java:21: error: element not allowed in documentation comments: + * <title> + ^ +9 errors diff --git a/langtools/test/tools/doclint/html/TableTagsTest.java b/langtools/test/tools/doclint/html/TableTagsTest.java new file mode 100644 index 00000000000..7cea1b35f9d --- /dev/null +++ b/langtools/test/tools/doclint/html/TableTagsTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006251 + * @summary test table tags + * @library .. + * @build DocLintTester + * @run main DocLintTester -Xmsgs TableTagsTest.java + */ + +/** */ +public class TableTagsTest { + /** + *
    + *
    + *
    abc
    + *
    + *
    + *
    + */ + public void supportedTags() { } +} diff --git a/langtools/test/tools/doclint/html/TagNotAllowed.java b/langtools/test/tools/doclint/html/TagNotAllowed.java new file mode 100644 index 00000000000..65a0bccddb4 --- /dev/null +++ b/langtools/test/tools/doclint/html/TagNotAllowed.java @@ -0,0 +1,30 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8004832 + * @summary Add new doclint package + * @library .. + * @build DocLintTester + * @run main DocLintTester -ref TagNotAllowed.out TagNotAllowed.java + */ + +/** + *

    abc
    term
    def
    description
    ghi
    + *
      abc
    1. item
    2. def
    3. item
    4. ghi
    + *
      abc
    • item
    • def
    • item
    • ghi
    + * + * abc
    + * abc
    + * abc
    + * abc
    + * abc
    + * + *
    + *   image
    + *   

    para

    + * text + * text + * text + * text + *
    + */ +public class TagNotAllowed { } diff --git a/langtools/test/tools/doclint/html/TagNotAllowed.out b/langtools/test/tools/doclint/html/TagNotAllowed.out new file mode 100644 index 00000000000..fa65f85d58a --- /dev/null +++ b/langtools/test/tools/doclint/html/TagNotAllowed.out @@ -0,0 +1,61 @@ +TagNotAllowed.java:11: error: tag not allowed here: + *
    abc
    term
    def
    description
    ghi
    + ^ +TagNotAllowed.java:11: error: tag not allowed here: + *
    abc
    term
    def
    description
    ghi
    + ^ +TagNotAllowed.java:11: error: tag not allowed here: + *
    abc
    term
    def
    description
    ghi
    + ^ +TagNotAllowed.java:12: error: tag not allowed here: + *
      abc
    1. item
    2. def
    3. item
    4. ghi
    + ^ +TagNotAllowed.java:12: error: tag not allowed here: + *
      abc
    1. item
    2. def
    3. item
    4. ghi
    + ^ +TagNotAllowed.java:12: error: tag not allowed here: + *
      abc
    1. item
    2. def
    3. item
    4. ghi
    + ^ +TagNotAllowed.java:13: error: tag not allowed here: + *
      abc
    • item
    • def
    • item
    • ghi
    + ^ +TagNotAllowed.java:13: error: tag not allowed here: + *
      abc
    • item
    • def
    • item
    • ghi
    + ^ +TagNotAllowed.java:13: error: tag not allowed here: + *
      abc
    • item
    • def
    • item
    • ghi
    + ^ +TagNotAllowed.java:15: error: tag not allowed here: + * abc
    + ^ +TagNotAllowed.java:16: error: tag not allowed here: + * abc
    + ^ +TagNotAllowed.java:17: error: tag not allowed here: + * abc
    + ^ +TagNotAllowed.java:18: error: tag not allowed here: + * abc
    + ^ +TagNotAllowed.java:19: error: tag not allowed here: + * abc
    + ^ +TagNotAllowed.java:22: error: tag not allowed here: + * image + ^ +TagNotAllowed.java:23: error: tag not allowed here:

    + *

    para

    + ^ +TagNotAllowed.java:24: error: tag not allowed here: + * text + ^ +TagNotAllowed.java:25: error: tag not allowed here: + * text + ^ +TagNotAllowed.java:26: error: tag not allowed here: + * text + ^ +TagNotAllowed.java:27: error: tag not allowed here: + * text + ^ +20 errors diff --git a/langtools/test/tools/doclint/html/TextNotAllowed.java b/langtools/test/tools/doclint/html/TextNotAllowed.java new file mode 100644 index 00000000000..6030a976994 --- /dev/null +++ b/langtools/test/tools/doclint/html/TextNotAllowed.java @@ -0,0 +1,32 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8004832 + * @summary Add new doclint package + * @library .. + * @build DocLintTester + * @run main DocLintTester -ref TextNotAllowed.out TextNotAllowed.java + */ + +/** + *
    abc
    term
    def
    description
    ghi
    + *
      abc
    1. item
    2. def
    3. item
    4. ghi
    + *
      abc
    • item
    • def
    • item
    • ghi
    + * + * abc
    + * abc
    + * abc
    + * abc
    + * abc
    + * + *
    &
    term
    <
    description
    >
    + *
      &
    1. item
    2. <
    3. item
    4. >
    + *
      &
    • item
    • <
    • item
    • >
    + * + * &
    + * &
    + * &
    + * &
    + * &
    + * + */ +public class TextNotAllowed { } diff --git a/langtools/test/tools/doclint/html/TextNotAllowed.out b/langtools/test/tools/doclint/html/TextNotAllowed.out new file mode 100644 index 00000000000..af5efa2e149 --- /dev/null +++ b/langtools/test/tools/doclint/html/TextNotAllowed.out @@ -0,0 +1,85 @@ +TextNotAllowed.java:11: error: text not allowed in
    element + *
    abc
    term
    def
    description
    ghi
    + ^ +TextNotAllowed.java:11: error: text not allowed in
    element + *
    abc
    term
    def
    description
    ghi
    + ^ +TextNotAllowed.java:11: error: text not allowed in
    element + *
    abc
    term
    def
    description
    ghi
    + ^ +TextNotAllowed.java:12: error: text not allowed in
      element + *
        abc
      1. item
      2. def
      3. item
      4. ghi
      + ^ +TextNotAllowed.java:12: error: text not allowed in
        element + *
          abc
        1. item
        2. def
        3. item
        4. ghi
        + ^ +TextNotAllowed.java:12: error: text not allowed in
          element + *
            abc
          1. item
          2. def
          3. item
          4. ghi
          + ^ +TextNotAllowed.java:13: error: text not allowed in
            element + *
              abc
            • item
            • def
            • item
            • ghi
            + ^ +TextNotAllowed.java:13: error: text not allowed in
              element + *
                abc
              • item
              • def
              • item
              • ghi
              + ^ +TextNotAllowed.java:13: error: text not allowed in
                element + *
                  abc
                • item
                • def
                • item
                • ghi
                + ^ +TextNotAllowed.java:15: error: text not allowed in element + *
                abc
                + ^ +TextNotAllowed.java:16: error: text not allowed in element + * abc
                + ^ +TextNotAllowed.java:17: error: text not allowed in element + * abc
                + ^ +TextNotAllowed.java:18: error: text not allowed in element + * abc
                + ^ +TextNotAllowed.java:19: error: text not allowed in element + * abc
                + ^ +TextNotAllowed.java:21: error: text not allowed in
                element + *
                &
                term
                <
                description
                >
                + ^ +TextNotAllowed.java:21: error: text not allowed in
                element + *
                &
                term
                <
                description
                >
                + ^ +TextNotAllowed.java:21: error: text not allowed in
                element + *
                &
                term
                <
                description
                >
                + ^ +TextNotAllowed.java:22: error: text not allowed in
                  element + *
                    &
                  1. item
                  2. <
                  3. item
                  4. >
                  + ^ +TextNotAllowed.java:22: error: text not allowed in
                    element + *
                      &
                    1. item
                    2. <
                    3. item
                    4. >
                    + ^ +TextNotAllowed.java:22: error: text not allowed in
                      element + *
                        &
                      1. item
                      2. <
                      3. item
                      4. >
                      + ^ +TextNotAllowed.java:23: error: text not allowed in
                        element + *
                          &
                        • item
                        • <
                        • item
                        • >
                        + ^ +TextNotAllowed.java:23: error: text not allowed in
                          element + *
                            &
                          • item
                          • <
                          • item
                          • >
                          + ^ +TextNotAllowed.java:23: error: text not allowed in
                            element + *
                              &
                            • item
                            • <
                            • item
                            • >
                            + ^ +TextNotAllowed.java:25: error: text not allowed in element + *
                            &
                            + ^ +TextNotAllowed.java:26: error: text not allowed in element + * &
                            + ^ +TextNotAllowed.java:27: error: text not allowed in element + * &
                            + ^ +TextNotAllowed.java:28: error: text not allowed in element + * &
                            + ^ +TextNotAllowed.java:29: error: text not allowed in element + * &
                            + ^ +28 errors diff --git a/langtools/test/tools/doclint/tidy/AAA.java b/langtools/test/tools/doclint/tidy/AAA.java new file mode 100644 index 00000000000..3880733edc9 --- /dev/null +++ b/langtools/test/tools/doclint/tidy/AAA.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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. + */ + +/** + * @test + * @bug 8006728 + * @summary temporarily workaround jtreg problems for doclint tests in othervm + */ + +// dummy test/class to be compiled before other tests in this directory +// see JDK-8006730 +public class AAA { + public static void main(String... args) { } +} + diff --git a/langtools/test/tools/doclint/tidy/ParaInPre.out b/langtools/test/tools/doclint/tidy/ParaInPre.out index bafe4aa7eed..ff9678128b1 100644 --- a/langtools/test/tools/doclint/tidy/ParaInPre.out +++ b/langtools/test/tools/doclint/tidy/ParaInPre.out @@ -1,4 +1,4 @@ -ParaInPre.java:16: warning: unexpected use of

                            inside

                             element
                            +ParaInPre.java:16: error: tag not allowed here: 

                            *

                            ^ -1 warning +1 error diff --git a/langtools/test/tools/doclint/tidy/TextNotAllowed.out b/langtools/test/tools/doclint/tidy/TextNotAllowed.out index 1a2944e1b04..cc6442f9315 100644 --- a/langtools/test/tools/doclint/tidy/TextNotAllowed.out +++ b/langtools/test/tools/doclint/tidy/TextNotAllowed.out @@ -1,19 +1,19 @@ TextNotAllowed.java:13: error: text not allowed in element *
                            abc
                            - ^ + ^ TextNotAllowed.java:14: error: text not allowed in element * abc
                            - ^ + ^ TextNotAllowed.java:15: error: text not allowed in element * abc
                            - ^ + ^ TextNotAllowed.java:17: error: text not allowed in

                            element *
                            abc
                            - ^ + ^ TextNotAllowed.java:18: error: text not allowed in
                              element *
                                abc
                              - ^ + ^ TextNotAllowed.java:19: error: text not allowed in
                                element *
                                  abc
                                - ^ + ^ 6 errors diff --git a/langtools/test/tools/doclint/tool/AAA.java b/langtools/test/tools/doclint/tool/AAA.java new file mode 100644 index 00000000000..3880733edc9 --- /dev/null +++ b/langtools/test/tools/doclint/tool/AAA.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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. + */ + +/** + * @test + * @bug 8006728 + * @summary temporarily workaround jtreg problems for doclint tests in othervm + */ + +// dummy test/class to be compiled before other tests in this directory +// see JDK-8006730 +public class AAA { + public static void main(String... args) { } +} + diff --git a/langtools/test/tools/doclint/tool/HelpTest.java b/langtools/test/tools/doclint/tool/HelpTest.java new file mode 100644 index 00000000000..936964a4636 --- /dev/null +++ b/langtools/test/tools/doclint/tool/HelpTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006263 + * @summary Supplementary test cases needed for doclint + * @library .. + * @build DocLintTester + * @run main DocLintTester -ref HelpTest.out + * @run main DocLintTester -ref HelpTest.out -h + * @run main DocLintTester -ref HelpTest.out -help + * @run main DocLintTester -ref HelpTest.out --help + * @run main DocLintTester -ref HelpTest.out -usage + * @run main DocLintTester -ref HelpTest.out -? + */ + + diff --git a/langtools/test/tools/doclint/tool/HelpTest.out b/langtools/test/tools/doclint/tool/HelpTest.out new file mode 100644 index 00000000000..78db573f178 --- /dev/null +++ b/langtools/test/tools/doclint/tool/HelpTest.out @@ -0,0 +1,43 @@ +Usage: + doclint [options] source-files... + +Options: + -Xmsgs + Same as -Xmsgs:all + -Xmsgs:values + Specify categories of issues to be checked, where 'values' + is a comma-separated list of any of the following: + reference show places where comments contain incorrect + references to Java source code elements + syntax show basic syntax errors within comments + html show issues with HTML tags and attributes + accessibility show issues for accessibility + missing show issues with missing documentation + all all of the above + Precede a value with '-' to negate it + Categories may be qualified by one of: + /public /protected /package /private + For positive categories (not beginning with '-') + the qualifier applies to that access level and above. + For negative categories (beginning with '-') + the qualifier applies to that access level and below. + If a qualifier is missing, the category applies to + all access levels. + For example, -Xmsgs:all,-syntax/private + This will enable all messages, except syntax errors + in the doc comments of private methods. + If no -Xmsgs options are provided, the default is + equivalent to -Xmsgs:all/protected, meaning that + all messages are reported for protected and public + declarations only. + -stats + Report statistics on the reported issues. + -h -help --help -usage -? + Show this message. + +The following javac options are also supported + -bootclasspath, -classpath, -sourcepath, -Xmaxerrs, -Xmaxwarns + +To run doclint on part of a project, put the compiled classes for your +project on the classpath (or bootclasspath), then specify the source files +to be checked on the command line. diff --git a/langtools/test/tools/doclint/tool/MaxDiagsTest.java b/langtools/test/tools/doclint/tool/MaxDiagsTest.java new file mode 100644 index 00000000000..0327ceb64db --- /dev/null +++ b/langtools/test/tools/doclint/tool/MaxDiagsTest.java @@ -0,0 +1,21 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006263 + * @summary Supplementary test cases needed for doclint + * @library .. + * @build DocLintTester + * @run main DocLintTester -ref MaxDiagsTest.out -Xmaxerrs 2 -Xmaxwarns 2 MaxDiagsTest.java + * @run main DocLintTester -badargs -Xmaxerrs + * @run main DocLintTester -badargs -Xmaxwarns + * @run main DocLintTester -badargs -Xmaxerrs two -Xmaxwarns two MaxDiagsTest.java + */ + +public class MaxDiagsTest { + /** + * � � � � + */ + public void errors() { } + + /** 4 undocumented signature items */ + public int warnings(int a1, int a2) throws Exception { return 0; } +} diff --git a/langtools/test/tools/doclint/tool/MaxDiagsTest.out b/langtools/test/tools/doclint/tool/MaxDiagsTest.out new file mode 100644 index 00000000000..ff5c9c84d37 --- /dev/null +++ b/langtools/test/tools/doclint/tool/MaxDiagsTest.out @@ -0,0 +1,14 @@ +MaxDiagsTest.java:13: warning: no comment +public class MaxDiagsTest { + ^ +MaxDiagsTest.java:15: error: invalid entity � + * � � � � + ^ +MaxDiagsTest.java:15: error: invalid entity � + * � � � � + ^ +MaxDiagsTest.java:20: warning: no @param for a1 + public int warnings(int a1, int a2) throws Exception { return 0; } + ^ +2 errors +2 warnings diff --git a/langtools/test/tools/doclint/tool/PathsTest.java b/langtools/test/tools/doclint/tool/PathsTest.java new file mode 100644 index 00000000000..e4cb2e2ae1e --- /dev/null +++ b/langtools/test/tools/doclint/tool/PathsTest.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006263 + * @summary Supplementary test cases needed for doclint + */ + +import com.sun.tools.doclint.DocLint; +import com.sun.tools.doclint.DocLint.BadArgs; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.regex.Pattern; + +public class PathsTest { + public static void main(String... args) throws Exception { + new PathsTest().run(); + } + + void run() throws Exception { + String PS = File.pathSeparator; + writeFile("src1/p/A.java", + "package p; public class A { }"); + compile("-d", "classes1", "src1/p/A.java"); + + writeFile("src2/q/B.java", + "package q; public class B extends p.A { }"); + compile("-d", "classes2", "-classpath", "classes1", "src2/q/B.java"); + + writeFile("src/Test.java", + "/** &0; */ class Test extends q.B { }"); + + test("src/Test.java", "-sourcepath", "src1" + PS + "src2"); + test("src/Test.java", "-classpath", "classes1" + PS + "classes2"); + String sysBootClassPath = System.getProperty("sun.boot.class.path"); + test("src/Test.java", "-bootclasspath", + sysBootClassPath + PS + "classes1" + PS + "classes2"); + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + Pattern pkgNotFound = Pattern.compile("package [a-z]+ does not exist"); + Pattern badHtmlEntity = Pattern.compile("bad HTML entity"); + + void test(String file, String pathOpt, String path) throws BadArgs, IOException { + System.err.println("test " + pathOpt); + String out1 = doclint("-Xmsgs", file); + if (!pkgNotFound.matcher(out1).find()) + error("message not found: " + pkgNotFound); + + String out2 = doclint("-Xmsgs", pathOpt, path, file); + if (pkgNotFound.matcher(out2).find()) + error("unexpected message found: " + pkgNotFound); + if (!badHtmlEntity.matcher(out1).find()) + error("message not found: " + badHtmlEntity); + + try { + doclint("-Xmsgs", pathOpt); + error("expected exception not thrown"); + } catch (BadArgs e) { + System.err.println(e); + } + } + + void compile(String... args) { + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-d")) { + new File(args[++i]).mkdirs(); + break; + } + } + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args, pw); + pw.close(); + String out = sw.toString(); + if (!out.isEmpty()) + System.err.println(out); + if (rc != 0) + error("compilation failed: rc=" + rc); + } + + String doclint(String... args) throws BadArgs, IOException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + DocLint dl = new DocLint(); + dl.run(pw, args); + pw.close(); + String out = sw.toString(); + if (!out.isEmpty()) + System.err.println(out); + return out; + } + + File writeFile(String path, String body) throws IOException { + File f = new File(path); + f.getParentFile().mkdirs(); + try (FileWriter fw = new FileWriter(path)) { + fw.write(body); + } + return f; + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; +} diff --git a/langtools/test/tools/doclint/tool/RunTest.java b/langtools/test/tools/doclint/tool/RunTest.java new file mode 100644 index 00000000000..e7dfa2da78e --- /dev/null +++ b/langtools/test/tools/doclint/tool/RunTest.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006263 + * @summary Supplementary test cases needed for doclint + */ + +import com.sun.source.util.JavacTask; +import com.sun.tools.doclint.DocLint; +import com.sun.tools.doclint.DocLint.BadArgs; +import com.sun.tools.javac.api.JavacTool; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URI; +import java.security.Permission; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; + +public class RunTest { + static class SimpleSecurityManager extends SecurityManager { + boolean allowExit = false; + + @Override + public void checkExit(int status) { + if (!allowExit) + throw new SecurityException("System.exit(" + status + ")"); + } + @Override + public void checkPermission(Permission perm) { } + + } + + public static void main(String... args) throws Exception { + // if no security manager already installed, install one to + // prevent System.exit + SimpleSecurityManager secmgr = null; + if (System.getSecurityManager() == null) { + System.setSecurityManager(secmgr = new SimpleSecurityManager() { }); + } + + try { + new RunTest().run(); + } finally { + if (secmgr != null) + secmgr.allowExit = true; + } + } + + void run() throws Exception { + testMain(); + testRun(); + testInit(); + testArgsNoFiles(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + void testMain() { + System.err.println("test main(String[])"); + testMain(true, "-help"); + testMain(false, "-unknownOption"); + } + + void testMain(boolean expectOK, String... args) { + try { + DocLint.main(args); + if (!expectOK) + error("expected SecurityException (from System.exit) not thrown"); + } catch (SecurityException e) { + System.err.println(e); + if (expectOK) + error("unexpected SecurityException caught"); + } + } + + void testRun() throws BadArgs, IOException { + System.err.println("test run(String[])"); + DocLint dl = new DocLint(); + String[] args = { "-help" }; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + PrintStream prev = System.out; + try { + System.setOut(ps); + dl.run(args); + } finally { + System.setOut(prev); + } + ps.close(); + String stdout = baos.toString(); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + dl.run(pw, args); + pw.close(); + String direct = sw.toString(); + + if (!stdout.equals(direct)) { + error("unexpected output"); + System.err.println("EXPECT>>" + direct + "<<"); + System.err.println("FOUND>>" + stdout + "<<"); + } + } + + void testInit() { + System.err.println("test init"); + DocLint dl = new DocLint(); + String name = dl.getName(); + if (!Objects.equals(name, "doclint")) + error("unexpected result for DocLint.getName()"); + + List files = + Arrays.asList(createFile("Test.java", "/** &0; */ class Test{ }")); + String[] goodArgs = { "-Xmsgs" }; + testInit(true, goodArgs, files); + + String[] badArgs = { "-unknown" }; + testInit(false, badArgs, files); + } + + void testInit(boolean expectOK, String[] args, List files) { + JavacTool javac = JavacTool.create(); + JavacTask task = javac.getTask(null, null, null, null, null, files); + try { + DocLint dl = new DocLint(); + dl.init(task, args, true); + if (!expectOK) + error("expected IllegalArgumentException not thrown"); + task.call(); + } catch (IllegalArgumentException e) { + System.err.println(e); + if (expectOK) + error("unexpected IllegalArgumentException caught"); + } + } + + void testArgsNoFiles() throws BadArgs, IOException { + System.err.println("test args, no files"); + DocLint dl = new DocLint(); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + dl.run(pw, "-Xmsgs"); + pw.close(); + String out = sw.toString(); + + String expect = "no files given"; + if (!Objects.equals(out.trim(), expect)) { + error("unexpected output"); + System.err.println("EXPECT>>" + expect + "<<"); + System.err.println("FOUND>>" + out + "<<"); + } + + } + + JavaFileObject createFile(String name, final String body) { + return new SimpleJavaFileObject(URI.create(name), JavaFileObject.Kind.SOURCE) { + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return body; + } + }; + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; +} diff --git a/langtools/test/tools/doclint/tool/StatsTest.java b/langtools/test/tools/doclint/tool/StatsTest.java new file mode 100644 index 00000000000..fd7077c3493 --- /dev/null +++ b/langtools/test/tools/doclint/tool/StatsTest.java @@ -0,0 +1,19 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006263 + * @summary Supplementary test cases needed for doclint + * @library .. + * @build DocLintTester + * @run main DocLintTester -ref StatsTest.out -stats -Xmsgs:all StatsTest.java + */ + +// warning: missing comment +public class StatsTest { + /** + * � � � � + */ + public void errors() { } + + /** 4 undocumented signature items */ + public int warnings(int a1, int a2) throws Exception { return 0; } +} diff --git a/langtools/test/tools/doclint/tool/StatsTest.out b/langtools/test/tools/doclint/tool/StatsTest.out new file mode 100644 index 00000000000..01d8fd2e3c9 --- /dev/null +++ b/langtools/test/tools/doclint/tool/StatsTest.out @@ -0,0 +1,43 @@ +StatsTest.java:11: warning: no comment +public class StatsTest { + ^ +StatsTest.java:13: error: invalid entity � + * � � � � + ^ +StatsTest.java:13: error: invalid entity � + * � � � � + ^ +StatsTest.java:13: error: invalid entity � + * � � � � + ^ +StatsTest.java:13: error: invalid entity � + * � � � � + ^ +StatsTest.java:18: warning: no @param for a1 + public int warnings(int a1, int a2) throws Exception { return 0; } + ^ +StatsTest.java:18: warning: no @param for a2 + public int warnings(int a1, int a2) throws Exception { return 0; } + ^ +StatsTest.java:18: warning: no @return + public int warnings(int a1, int a2) throws Exception { return 0; } + ^ +StatsTest.java:18: warning: no @throws for java.lang.Exception + public int warnings(int a1, int a2) throws Exception { return 0; } + ^ +By group... + 5: missing + 4: html + +By diagnostic kind... + 5: warning + 4: error + +By message kind... + 4: invalid entity &{0}; + 2: no @param for {0} + 1: no @return + 1: no @throws for {0} + 1: no comment +4 errors +5 warnings diff --git a/langtools/test/tools/javac/7129225/TestImportStar.java b/langtools/test/tools/javac/7129225/TestImportStar.java index c22e5b9d4ec..eaca9ed23c3 100644 --- a/langtools/test/tools/javac/7129225/TestImportStar.java +++ b/langtools/test/tools/javac/7129225/TestImportStar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,7 +30,7 @@ * @build JavacTestingAbstractProcessor * @compile/fail/ref=NegTest.ref -XDrawDiagnostics TestImportStar.java * @compile Anno.java AnnoProcessor.java - * @compile/ref=TestImportStar.ref -XDrawDiagnostics -processor AnnoProcessor -proc:only TestImportStar.java + * @compile/fail/ref=TestImportStar.ref -XDrawDiagnostics -processor AnnoProcessor -proc:only TestImportStar.java */ //The @compile/fail... verifies that the fix doesn't break the normal compilation of import xxx.* diff --git a/langtools/test/tools/javac/7129225/TestImportStar.ref b/langtools/test/tools/javac/7129225/TestImportStar.ref index 6248faddde8..5b3c75d7d89 100644 --- a/langtools/test/tools/javac/7129225/TestImportStar.ref +++ b/langtools/test/tools/javac/7129225/TestImportStar.ref @@ -1,3 +1,4 @@ - compiler.note.proc.messager: RUNNING - lastRound = false TestImportStar.java:39:1: compiler.err.doesnt.exist: xxx - compiler.note.proc.messager: RUNNING - lastRound = true +1 error \ No newline at end of file diff --git a/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java b/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java new file mode 100644 index 00000000000..c30927484ab --- /dev/null +++ b/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012, 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. + */ + +/* + * @test + * @bug 7199823 + * @summary javac generates inner class that can't be verified + * @run main InnerClassCannotBeVerified + */ + +import java.util.Arrays; +import javax.tools.JavaFileObject; +import java.net.URI; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; +import javax.tools.JavaCompiler; +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; +import java.io.File; +import java.io.IOException; + +public class InnerClassCannotBeVerified { + + private static final String errorMessage = + "Compile error while compiling the following source:\n"; + + public static void main(String... args) throws Exception { + new InnerClassCannotBeVerified().run(); + } + + void run() throws Exception { + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + JavaSource source = new JavaSource(); + JavacTask ct = (JavacTask)comp.getTask(null, null, null, + null, null, Arrays.asList(source)); + try { + if (!ct.call()) { + throw new AssertionError(errorMessage + + source.getCharContent(true)); + } + } catch (Throwable ex) { + throw new AssertionError(errorMessage + + source.getCharContent(true)); + } + check(); + } + + private void check() throws IOException, ConstantPoolException { + File file = new File("Test$1.class"); + ClassFile classFile = ClassFile.read(file); + boolean inheritsFromObject = + classFile.getSuperclassName().equals("java/lang/Object"); + boolean implementsNoInterface = classFile.interfaces.length == 0; + boolean noMethods = classFile.methods.length == 0; + if (!(inheritsFromObject && + implementsNoInterface && + noMethods)) { + throw new AssertionError("The inner classes reused as " + + "access constructor tag for this code must be empty"); + } + } + + class JavaSource extends SimpleJavaFileObject { + + String internalSource = + "public class Test {\n" + + " private static class Foo {}\n" + + " public static void main(String[] args){ \n" + + " new Foo();\n" + + " if(false) {\n" + + " new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " System.out.println();\n" + + " }\n" + + " }.run();\n" + + " }\n" + + " }\n" + + "}"; + public JavaSource() { + super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return internalSource; + } + } +} diff --git a/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_1.out b/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_1.out index 357c45f6ec2..48bd8d3b403 100644 --- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_1.out +++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_1.out @@ -1,3 +1,3 @@ -T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.intersection.type: 1, T6722234d.A) +T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: compiler.misc.intersection.type: 1, T6722234d.A,java.lang.Object) - compiler.misc.where.description.intersection: compiler.misc.intersection.type: 1,{(compiler.misc.where.intersection: compiler.misc.intersection.type: 1, java.lang.Object,T6722234d.I1,T6722234d.I2)} 1 error diff --git a/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_2.out b/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_2.out index ada2508b3f2..dd1d1de380b 100644 --- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_2.out +++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234d_2.out @@ -1,3 +1,3 @@ -T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.intersection.type: 1, T6722234d.A) +T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: compiler.misc.intersection.type: 1, T6722234d.A,Object) - compiler.misc.where.description.intersection: compiler.misc.intersection.type: 1,{(compiler.misc.where.intersection: compiler.misc.intersection.type: 1, Object,I1,I2)} 1 error diff --git a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java index 8339124619e..2d9bf1810ef 100644 --- a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java +++ b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java @@ -23,14 +23,18 @@ /** * @test - * @bug 6769027 + * @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 * @build JavacTestingAbstractThreadedTest * @run main/othervm T6769027 */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.regex.Matcher; import javax.tools.*; @@ -488,7 +492,7 @@ public class T6769027 } if (!msg.equals(errorLine)) { - printInfo(msg, errorLine); +// printInfo(msg, errorLine); errCount.incrementAndGet(); } } diff --git a/langtools/test/tools/javac/T6873845.java b/langtools/test/tools/javac/T6873845.java index ff84028326f..b1cfea6d203 100644 --- a/langtools/test/tools/javac/T6873845.java +++ b/langtools/test/tools/javac/T6873845.java @@ -19,8 +19,8 @@ public class T6873845 { if (out.contains("sunapi")) throw new Exception("unexpected output for -X"); - String warn1 = "T6873845.java:72:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; - String warn2 = "T6873845.java:77:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; + String warn1 = "T6873845.java:73:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; + String warn2 = "T6873845.java:78:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline; String note1 = "- compiler.note.sunapi.filename: T6873845.java" + newline; String note2 = "- compiler.note.sunapi.recompile" + newline; @@ -52,7 +52,8 @@ public class T6873845 { args.add(0, "-XDrawDiagnostics"); String out = compile(args); if (!out.equals(expect)) - throw new Exception("unexpected output from compiler"); + throw new Exception("unexpected output from compiler; expected: " + expect + + "\n found: " + out); } String compile(List args) throws Exception{ diff --git a/langtools/test/tools/javac/T6985181.java b/langtools/test/tools/javac/T6985181.java new file mode 100644 index 00000000000..2211ff45fc2 --- /dev/null +++ b/langtools/test/tools/javac/T6985181.java @@ -0,0 +1,88 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6985181 + * @summary Annotations lost from classfile + */ + +import java.io.*; +import java.util.*; + +public class T6985181 { + public static void main(String... args) throws Exception{ + new T6985181().run(); + } + + public void run() throws Exception { + String code = "@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_PARAMETER)\n" + + "@interface Simple { }\n" + + "interface Test<@Simple T> { }"; + + File srcFile = writeFile("Test.java", code); + File classesDir = new File("classes"); + classesDir.mkdirs(); + compile("-d", classesDir.getPath(), srcFile.getPath()); + String out = javap(new File(classesDir, srcFile.getName().replace(".java", ".class"))); + if (!out.contains("RuntimeInvisibleTypeAnnotations")) + throw new Exception("RuntimeInvisibleTypeAnnotations not found"); + } + + void compile(String... args) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args, pw); + pw.close(); + String out = sw.toString(); + if (out.length() > 0) + System.err.println(out); + if (rc != 0) + throw new Exception("Compilation failed: rc=" + rc); + } + + String javap(File classFile) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + String[] args = { "-v", classFile.getPath() }; + int rc = com.sun.tools.javap.Main.run(args, pw); + pw.close(); + String out = sw.toString(); + if (out.length() > 0) + System.err.println(out); + if (rc != 0) + throw new Exception("javap failed: rc=" + rc); + return out; + } + + File writeFile(String path, String body) throws IOException { + File f = new File(path); + FileWriter out = new FileWriter(f); + try { + out.write(body); + } finally { + out.close(); + } + return f; + } +} diff --git a/langtools/test/tools/javac/T7093325.java b/langtools/test/tools/javac/T7093325.java index 8330ede8624..dcdc6e62856 100644 --- a/langtools/test/tools/javac/T7093325.java +++ b/langtools/test/tools/javac/T7093325.java @@ -23,13 +23,17 @@ /* * @test - * @bug 7093325 + * @bug 7093325 8006694 * @summary Redundant entry in bytecode exception table + * temporarily workaround combo tests are causing time out in several platforms * @library lib * @build JavacTestingAbstractThreadedTest - * @run main T7093325 + * @run main/othervm T7093325 */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.io.File; import java.net.URI; import java.util.Arrays; @@ -171,8 +175,6 @@ public class T7093325 gapsCount++; } - //System.out.printf("gaps %d \n %s \n", gapsCount, source.toString()); - File compiledTest = new File(String.format("Test%s.class", id)); try { ClassFile cf = ClassFile.read(compiledTest); diff --git a/langtools/test/tools/javac/annotations/6881115/T6881115.java b/langtools/test/tools/javac/annotations/6881115/T6881115.java index 2f779c4ac46..0c917f15c64 100644 --- a/langtools/test/tools/javac/annotations/6881115/T6881115.java +++ b/langtools/test/tools/javac/annotations/6881115/T6881115.java @@ -1,3 +1,6 @@ +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + /* * @test /nodynamiccopyright/ * @bug 6881115 6976649 @@ -6,15 +9,18 @@ * @compile/fail/ref=T6881115.out -XDrawDiagnostics T6881115.java */ +@Target({ElementType.TYPE, ElementType.TYPE_PARAMETER, ElementType.ANNOTATION_TYPE}) @interface A { B b() default @B(b2 = 1, b2 = 2); B[] b_arr() default {@B(), @B(b2 = 1, b2 = 2)}; } + @interface B { String b1(); int b2(); } + @A(b = @B(b2 = 1, b2 = 2), b_arr = {@B(), @B(b2 = 1, b2 = 2)}) -class T6881115 {} +class T6881115<@A(b = @B(b2 = 1, b2 = 2), + b_arr = {@B(), @B(b2 = 1, b2 = 2)}) X> {} diff --git a/langtools/test/tools/javac/annotations/6881115/T6881115.out b/langtools/test/tools/javac/annotations/6881115/T6881115.out index 93b90cff473..a924a311590 100644 --- a/langtools/test/tools/javac/annotations/6881115/T6881115.out +++ b/langtools/test/tools/javac/annotations/6881115/T6881115.out @@ -1,11 +1,16 @@ -T6881115.java:10:30: compiler.err.duplicate.annotation.member.value: b2, B -T6881115.java:10:19: compiler.err.annotation.missing.default.value: B, b1 -T6881115.java:11:26: compiler.err.annotation.missing.default.value.1: B, b1,b2 -T6881115.java:11:43: compiler.err.duplicate.annotation.member.value: b2, B -T6881115.java:11:32: compiler.err.annotation.missing.default.value: B, b1 -T6881115.java:17:19: compiler.err.duplicate.annotation.member.value: b2, B -T6881115.java:17:8: compiler.err.annotation.missing.default.value: B, b1 -T6881115.java:18:13: compiler.err.annotation.missing.default.value.1: B, b1,b2 -T6881115.java:18:30: compiler.err.duplicate.annotation.member.value: b2, B -T6881115.java:18:19: compiler.err.annotation.missing.default.value: B, b1 -10 errors +T6881115.java:14:30: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:14:19: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:15:26: compiler.err.annotation.missing.default.value.1: B, b1,b2 +T6881115.java:15:43: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:15:32: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:23:19: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:23:8: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:24:13: compiler.err.annotation.missing.default.value.1: B, b1,b2 +T6881115.java:24:30: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:24:19: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:25:34: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:25:23: compiler.err.annotation.missing.default.value: B, b1 +T6881115.java:26:28: compiler.err.annotation.missing.default.value.1: B, b1,b2 +T6881115.java:26:45: compiler.err.duplicate.annotation.member.value: b2, B +T6881115.java:26:34: compiler.err.annotation.missing.default.value: B, b1 +15 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.java index d508fea04c7..baf8b14363a 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.java @@ -6,11 +6,9 @@ * @compile/fail/ref=BaseAnnoAsContainerAnno.out -XDrawDiagnostics BaseAnnoAsContainerAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(Foo.class) -@ContainerFor(Foo.class) +@Repeatable(Foo.class) @interface Foo { Foo[] value() default {}; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.out index 8f2419f297b..0d6975ac424 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/BaseAnnoAsContainerAnno.out @@ -1,2 +1,2 @@ -BaseAnnoAsContainerAnno.java:15:11: compiler.err.cyclic.annotation.element +BaseAnnoAsContainerAnno.java:13:11: compiler.err.cyclic.annotation.element 1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java index 9d9e59c1fc4..848cd18cc39 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,10 +34,9 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} -@ContainerFor(Foo.class) @Retention(RetentionPolicy.RUNTIME) @interface Foos { Foo[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java index 1489cea562d..bdcfb1e51dc 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,32 +32,29 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @Target(ElementType.TYPE) @interface Foo {} -@ContainerFor(Foo.class) @Target(ElementType.ANNOTATION_TYPE) @interface Foos { Foo[] value(); } -@ContainedBy(Bars.class) +@Repeatable(Bars.class) @Target(ElementType.TYPE) @interface Bar {} -@ContainerFor(Bar.class) @Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE }) @interface Bars { Bar[] value(); } -@ContainedBy(Bazs.class) +@Repeatable(Bazs.class) @Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) @interface Baz {} -@ContainerFor(Baz.class) @Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE }) @interface Bazs { Baz[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/ClassReaderDefault.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/ClassReaderDefault.java index 18d9d7c6a41..f441f5b046c 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/ClassReaderDefault.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/ClassReaderDefault.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,17 +30,15 @@ * @compile ClassReaderDefault.java * @compile SeparateCompile.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; public class ClassReaderDefault { } -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); int f() default 0; } -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java index ca2345d6b16..86cb6a071bd 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,15 +30,13 @@ * @run compile ContainerHasRepeatedContained.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(BarContainer.class) +@Repeatable(BarContainer.class) @interface Bar {} @Bar @Bar -@ContainerFor(Bar.class) @interface BarContainer { Bar[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.java index 7549d464d5f..82d52700459 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.java @@ -6,17 +6,14 @@ * @compile/fail/ref=CyclicAnnotation.out -XDrawDiagnostics CyclicAnnotation.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(Foo.class) -@ContainerFor(Baz.class) +@Repeatable(Foo.class) @interface Baz { Foo[] value() default {}; } -@ContainedBy(Baz.class) -@ContainerFor(Foo.class) +@Repeatable(Baz.class) @interface Foo{ Baz[] value() default {}; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.out index 070b8ca0883..84079dd77b4 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/CyclicAnnotation.out @@ -1,6 +1,2 @@ -CyclicAnnotation.java:12:1: compiler.err.invalid.container.wrong.containerfor: Foo, Baz -CyclicAnnotation.java:13:1: compiler.err.invalid.container.wrong.containedby: Foo, Baz -CyclicAnnotation.java:15:11: compiler.err.cyclic.annotation.element -CyclicAnnotation.java:18:1: compiler.err.invalid.container.wrong.containerfor: Baz, Foo -CyclicAnnotation.java:19:1: compiler.err.invalid.container.wrong.containedby: Baz, Foo -5 errors +CyclicAnnotation.java:13:11: compiler.err.cyclic.annotation.element +1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DefaultCasePresent.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/DefaultCasePresent.java index 7352a622119..4f8778d4488 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/DefaultCasePresent.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DefaultCasePresent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,13 +29,11 @@ * @compile DefaultCasePresent.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); String other() default "other-method"; diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java index ffceb9c3707..939ce4a3266 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -39,12 +39,11 @@ public class DelayRepeatedContainer { @Bar("katt") @Bar("lol") -@ContainedBy(BarContainer.class) +@Repeatable(BarContainer.class) @interface Bar { String value(); } -@ContainerFor(Bar.class) @interface BarContainer { Bar[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.java index 96d86f7a368..95fd96ceda2 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.java @@ -6,15 +6,13 @@ * @compile/fail/ref=DocumentedContainerAnno.out -XDrawDiagnostics DocumentedContainerAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; import java.lang.annotation.Documented; @Documented -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer{ Foo[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.out index 409d0414e77..bb267c47af3 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DocumentedContainerAnno.out @@ -1,2 +1,2 @@ -DocumentedContainerAnno.java:14:1: compiler.err.invalid.containedby.annotation.not.documented: FooContainer, Foo +DocumentedContainerAnno.java:13:1: compiler.err.invalid.repeatable.annotation.not.documented: FooContainer, Foo 1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.java index 2d2a9c63894..20f8ad25224 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.java @@ -6,15 +6,13 @@ * @compile/fail/ref=InheritedContainerAnno.out -XDrawDiagnostics InheritedContainerAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; import java.lang.annotation.Inherited; @Inherited -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer{ Foo[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.out index 10fcc772581..43736227f0d 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/InheritedContainerAnno.out @@ -1,2 +1,2 @@ -InheritedContainerAnno.java:14:1: compiler.err.invalid.containedby.annotation.not.inherited: FooContainer, Foo +InheritedContainerAnno.java:13:1: compiler.err.invalid.repeatable.annotation.not.inherited: FooContainer, Foo 1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java index 24c23386033..f85924a5d4c 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,11 +32,10 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @Target(ElementType.ANNOTATION_TYPE) @interface Foo {} -@ContainerFor(Foo.class) @Target(ElementType.TYPE) @interface Foos { Foo[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.java index 8e5650442dc..e35273e0f4a 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.java @@ -6,13 +6,11 @@ * @compile/fail/ref=MissingContainer.out -XDrawDiagnostics MissingContainer.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy() +@Repeatable() @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.out index 76986a76769..5a0e89df1ee 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainer.out @@ -1,5 +1,4 @@ -MissingContainer.java:20:1: compiler.err.invalid.containedby.annotation: Foo -MissingContainer.java:20:6: compiler.err.invalid.containedby.annotation: Foo -MissingContainer.java:12:1: compiler.err.annotation.missing.default.value: java.lang.annotation.ContainedBy, value -MissingContainer.java:15:1: compiler.err.invalid.container.wrong.containedby: Foo, FooContainer -4 errors +MissingContainer.java:18:1: compiler.err.invalid.repeatable.annotation: Foo +MissingContainer.java:18:6: compiler.err.invalid.repeatable.annotation: Foo +MissingContainer.java:11:1: compiler.err.annotation.missing.default.value: java.lang.annotation.Repeatable, value +3 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java index c29d0e8afa7..478154738c6 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java @@ -6,13 +6,11 @@ * @compile/fail/ref=MissingDefaultCase1.out -XDrawDiagnostics MissingDefaultCase1.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); String other(); // missing default clause diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out index ae188503866..474b6c16451 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out @@ -1,3 +1,3 @@ -MissingDefaultCase1.java:21:1: compiler.err.duplicate.annotation.invalid.repeated: Foo -MissingDefaultCase1.java:12:1: compiler.err.invalid.containedby.annotation.elem.nondefault: FooContainer, other() +MissingDefaultCase1.java:19:1: compiler.err.duplicate.annotation.invalid.repeated: Foo +MissingDefaultCase1.java:11:1: compiler.err.invalid.repeatable.annotation.elem.nondefault: FooContainer, other() 2 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java index b0b42b40cfc..73f2cfe6500 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java @@ -6,13 +6,11 @@ * @compile/fail/ref=MissingDefaultCase2.out -XDrawDiagnostics MissingDefaultCase2.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); Foo other(); // missing default clause and return type is an annotation diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out index 7e3a4229587..de467107770 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out @@ -1,3 +1,3 @@ -MissingDefaultCase2.java:21:1: compiler.err.duplicate.annotation.invalid.repeated: Foo -MissingDefaultCase2.java:12:1: compiler.err.invalid.containedby.annotation.elem.nondefault: FooContainer, other() +MissingDefaultCase2.java:19:1: compiler.err.duplicate.annotation.invalid.repeated: Foo +MissingDefaultCase2.java:11:1: compiler.err.invalid.repeatable.annotation.elem.nondefault: FooContainer, other() 2 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.java index 36333b75cb2..a539a94c59a 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.java @@ -6,13 +6,11 @@ * @compile/fail/ref=MissingValueMethod.out -XDrawDiagnostics MissingValueMethod.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainerFor(Foo.class) @interface FooContainer{ Foo[] values(); // wrong method name } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.out index a712b5fa798..bb1e8888d61 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingValueMethod.out @@ -1,4 +1,4 @@ -MissingValueMethod.java:20:1: compiler.err.invalid.containedby.annotation.no.value: FooContainer -MissingValueMethod.java:20:6: compiler.err.invalid.containedby.annotation.no.value: FooContainer -MissingValueMethod.java:12:1: compiler.err.invalid.containedby.annotation.elem.nondefault: FooContainer, values() +MissingValueMethod.java:18:1: compiler.err.invalid.repeatable.annotation.no.value: FooContainer +MissingValueMethod.java:18:6: compiler.err.invalid.repeatable.annotation.no.value: FooContainer +MissingValueMethod.java:11:1: compiler.err.invalid.repeatable.annotation.no.value: FooContainer 3 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MultiLevelRepeatableAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MultiLevelRepeatableAnno.java index 62b0089e0a4..8459f863329 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MultiLevelRepeatableAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MultiLevelRepeatableAnno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,19 +29,16 @@ * @compile MultiLevelRepeatableAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo {} -@ContainedBy(FooContainerContainer.class) -@ContainerFor(Foo.class) +@Repeatable(FooContainerContainer.class) @interface FooContainer { Foo[] value(); } -@ContainerFor(FooContainer.class) @interface FooContainerContainer { FooContainer[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MultipleAnnoMixedOrder.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MultipleAnnoMixedOrder.java index 0de0c3221a0..5992dfc8ee7 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MultipleAnnoMixedOrder.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MultipleAnnoMixedOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,25 +29,22 @@ * @compile MultipleAnnoMixedOrder.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo { int getNumbers(); } -@ContainerFor(Foo.class) @interface FooContainer { Foo[] value(); } -@ContainedBy(BazContainer.class) +@Repeatable(BazContainer.class) @interface Baz { String getStr(); } -@ContainerFor(Baz.class) @interface BazContainer { Baz[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java index c492258801a..4694989e821 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,17 +34,15 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(FoosFoos.class) -@ContainerFor(Foo.class) +@Repeatable(FoosFoos.class) @interface Foos { Foo[] value(); } -@ContainerFor(Foos.class) @Retention(RetentionPolicy.RUNTIME) @interface FoosFoos { Foos[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out index 42a8105b79d..1af160338c3 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out @@ -1,3 +1,3 @@ -NoRepeatableAnno.java:11:1: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.ContainedBy -NoRepeatableAnno.java:11:6: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.ContainedBy +NoRepeatableAnno.java:11:1: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.Repeatable +NoRepeatableAnno.java:11:6: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.Repeatable 2 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java index bb67c91cee0..2a6fc880f3f 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,20 +30,18 @@ * @run compile RepMemberAnno.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; public class RepMemberAnno { @Bar("Apa") @Bar("Banan") public void meh() {} } -@ContainedBy(BarContainer.class) +@Repeatable(BarContainer.class) @interface Bar { String value(); } -@ContainerFor(Bar.class) @interface BarContainer { Bar[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java index bc11c69c1f0..79fdf213863 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,21 +34,19 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(BarContainer.class) +@Repeatable(BarContainer.class) public @interface RepSelfMemberAnno { @RepSelfMemberAnno @RepSelfMemberAnno String meh() default "banan"; } -@ContainedBy(BarContainerContainer.class) +@Repeatable(BarContainerContainer.class) @Retention(RetentionPolicy.RUNTIME) -@ContainerFor(RepSelfMemberAnno.class) @interface BarContainer { RepSelfMemberAnno[] value(); } -@ContainerFor(BarContainer.class) @Retention(RetentionPolicy.RUNTIME) @interface BarContainerContainer { BarContainer[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java index 26d98513502..62bc29f10bc 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,7 +30,7 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} @interface Foos { diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java index 7210b3f573b..7d2ba5e7673 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -31,10 +31,9 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} -@ContainerFor(Foo.class) @Target(ElementType.ANNOTATION_TYPE) @interface Foos { Foo[] value(); diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out index fd4b6acc4cc..7979c8213b9 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out @@ -1,2 +1,2 @@ -RepeatingTargetNotAllowed.java:44:5: compiler.err.invalid.containedby.annotation.incompatible.target: Foos, Foo +RepeatingTargetNotAllowed.java:43:5: compiler.err.invalid.repeatable.annotation.incompatible.target: Foos, Foo 1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java index b0eb87d876b..7a70c90562d 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -33,7 +33,6 @@ import java.lang.annotation.*; -@ContainerFor(SelfRepeatingAnno.class) @Retention(RetentionPolicy.RUNTIME) @interface Foos { SelfRepeatingAnno[] value(); @@ -42,7 +41,7 @@ import java.lang.annotation.*; @SelfRepeatingAnno @Retention(RetentionPolicy.RUNTIME) @SelfRepeatingAnno -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface SelfRepeatingAnno {} public class SelfRepeatingAnnotations { diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java index b18d259670f..56cc83ca5d6 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,10 +30,9 @@ import java.lang.annotation.*; -@ContainedBy(Foos.class) +@Repeatable(Foos.class) @interface Foo {} -@ContainerFor(Foo.class) @interface Foos { Foo[] value(); } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java similarity index 79% rename from langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java rename to langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java index 0a141a9e129..8d4b37f4c31 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -24,16 +24,18 @@ /** * @test * @summary Smoke test for repeating annotations - * @compile/fail MissingContainedBy.java + * @compile/fail UseWrongRepeatable.java * @bug 7151010 */ import java.lang.annotation.*; - -@ContainerFor(MissingContainedBy.class) @interface Foos { - MissingContainedBy[] value(); + UseWrongRepeatable[] value(); } -public @interface MissingContainedBy {} +@Repeatable(Target.class) +public @interface UseWrongRepeatable {} + +@UseWrongRepeatable @UseWrongRepeatable +@interface Foo {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.java index 6573f2f86e7..69f25b6985a 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.java @@ -6,15 +6,13 @@ * @compile/fail/ref=WrongReturnTypeForValue.out -XDrawDiagnostics WrongReturnTypeForValue.java */ -import java.lang.annotation.ContainedBy; -import java.lang.annotation.ContainerFor; +import java.lang.annotation.Repeatable; -@ContainedBy(FooContainer.class) +@Repeatable(FooContainer.class) @interface Foo { int getNumbers(); } -@ContainerFor(Foo.class) @interface FooContainer{ Foo value(); // wrong return type } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.out index aa2c6384851..add7bbaa3ae 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.out +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongReturnTypeForValue.out @@ -1,3 +1,4 @@ -WrongReturnTypeForValue.java:22:1: compiler.err.invalid.containedby.annotation.value.return: FooContainer, Foo, Foo[] -WrongReturnTypeForValue.java:22:6: compiler.err.invalid.containedby.annotation.value.return: FooContainer, Foo, Foo[] -2 errors +WrongReturnTypeForValue.java:20:1: compiler.err.invalid.repeatable.annotation.value.return: FooContainer, Foo, Foo[] +WrongReturnTypeForValue.java:20:6: compiler.err.invalid.repeatable.annotation.value.return: FooContainer, Foo, Foo[] +WrongReturnTypeForValue.java:11:1: compiler.err.invalid.repeatable.annotation.value.return: FooContainer, Foo, Foo[] +3 errors diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java index 802f631f5b1..03e9dbe8e37 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/BasicSyntaxCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -163,9 +163,8 @@ public class BasicSyntaxCombo extends Helper{ String replaceStr = "/*"+type+"*/"; StringBuilder annoData = new StringBuilder(); annoData.append(Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); JavaFileObject pkgInfoFile = null; diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java index ba4e1652a03..8a2bcca1f30 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DeprecatedAnnoCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -115,24 +115,21 @@ public class DeprecatedAnnoCombo extends Helper { switch(className) { case "DeprecatedonBoth": annoData.append(Helper.ContentVars.DEPRECATED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) .append(Helper.ContentVars.DEPRECATED.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; case "DeprecatedonBase": - annoData.append(Helper.ContentVars.CONTAINERFOR.getVal()) - .append(Helper.ContentVars.CONTAINER.getVal()) + annoData.append(Helper.ContentVars.CONTAINER.getVal()) .append(Helper.ContentVars.DEPRECATED.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; case "DeprecatedonContainer": annoData.append(Helper.ContentVars.DEPRECATED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java index dbe38afd768..4bb3728dda0 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/DocumentedAnnoCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -93,17 +93,15 @@ public class DocumentedAnnoCombo extends Helper { switch(className) { case "DocumentedonBothAnno": annoData.append(Helper.ContentVars.DOCUMENTED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) .append(Helper.ContentVars.DOCUMENTED.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; case "DocumentedonContainer": annoData.append(Helper.ContentVars.DOCUMENTED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java index 653c2f5ce0a..8a0109578c1 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/Helper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,15 +34,13 @@ import javax.tools.JavaCompiler.CompilationTask; public class Helper { enum ContentVars { - IMPORTCONTAINERSTMTS("\nimport java.lang.annotation.ContainedBy;\n" + - "\nimport java.lang.annotation.ContainerFor;\n"), + IMPORTCONTAINERSTMTS("\nimport java.lang.annotation.Repeatable;\n"), IMPORTDEPRECATED("import java.lang.Deprecated;\n"), IMPORTDOCUMENTED("import java.lang.annotation.Documented;\n"), IMPORTINHERITED("import java.lang.annotation.Inherited;\n"), IMPORTRETENTION("import java.lang.annotation.Retention;\n" + "\nimport java.lang.annotation.RetentionPolicy;\n"), - CONTAINEDBY("\n@ContainedBy(FooContainer.class)\n"), - CONTAINERFOR("@ContainerFor(Foo.class)\n"), + REPEATABLE("\n@Repeatable(FooContainer.class)\n"), CONTAINER("@interface FooContainer {\n" +" Foo[] value();\n}\n"), BASE("@interface Foo {}\n"), REPEATABLEANNO("\n@Foo() @Foo()"), diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java index b0b019f065d..cb49350f6fd 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/InheritedAnnoCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -94,17 +94,15 @@ public class InheritedAnnoCombo extends Helper { switch(className) { case "InheritedonBothAnno": annoData.append(Helper.ContentVars.INHERITED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) .append(Helper.ContentVars.INHERITED.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; case "InheritedonBase": annoData.append(Helper.ContentVars.INHERITED.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(Helper.ContentVars.BASE.getVal()); break; } diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java index 99c5c5eb0ce..3a5ebaf142b 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/combo/RetentionAnnoCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -120,7 +120,7 @@ public class RetentionAnnoCombo extends Helper { new DiagnosticCollector(); boolean ok = compileCode(className, contents, diagnostics); - String expectedErrKey = "compiler.err.invalid.containedby" + + String expectedErrKey = "compiler.err.invalid.repeatable" + ".annotation.retention"; if (!shouldCompile && !ok) { for (Diagnostic d : diagnostics.getDiagnostics()) { @@ -175,10 +175,9 @@ public class RetentionAnnoCombo extends Helper { StringBuilder annoData = new StringBuilder(); annoData.append(Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal()) .append(Helper.ContentVars.IMPORTRETENTION.getVal()) - .append(Helper.ContentVars.CONTAINERFOR.getVal()) .append(replacedRetCAVal) .append(Helper.ContentVars.CONTAINER.getVal()) - .append(Helper.ContentVars.CONTAINEDBY.getVal()) + .append(Helper.ContentVars.REPEATABLE.getVal()) .append(replacedRetBaseVal) .append(Helper.ContentVars.BASE.getVal()); diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.java b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.java new file mode 100644 index 00000000000..a0cbc78c690 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/* + * @test + * @bug 6967002 8006775 + * @summary JDK7 b99 javac compilation error (java.lang.AssertionError) + * @author Maurizio Cimadamore + * @compile/fail/ref=T6967002.out -XDrawDiagnostics T6967002.java + */ +class Test { + private static void m(byte[] octets) { + return m(octets..., ?); + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out new file mode 100644 index 00000000000..18b75307f04 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out @@ -0,0 +1,8 @@ +T6967002.java:33:22: compiler.err.expected: ')' +T6967002.java:33:25: compiler.err.illegal.start.of.expr +T6967002.java:33:28: compiler.err.illegal.start.of.expr +T6967002.java:33:29: compiler.err.illegal.start.of.expr +T6967002.java:33:27: compiler.err.not.stmt +T6967002.java:33:30: compiler.err.expected: ';' +T6967002.java:35:2: compiler.err.premature.eof +7 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/InnerClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/InnerClass.java new file mode 100644 index 00000000000..53cab9fa589 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/InnerClass.java @@ -0,0 +1,65 @@ +import java.lang.annotation.ElementType; + +/* + * Copyright (c) 2009, 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. + */ + +/* + * @test + * @bug 6843077 8006775 + * @summary compiler crashes when visiting inner classes + * @author Mahmood Ali + * @compile InnerClass.java + */ + +import java.lang.annotation.*; + +class InnerClass { + + InnerClass() {} + InnerClass(Object o) {} + + private void a() { + new Object() { + public void method() { } + }; + } + + Object f1 = new InnerClass() { + void method() { } + }; + + Object f2 = new InnerClass() { + <@A R> void method() { } + }; + + Object f3 = new InnerClass(null) { + void method() { } + }; + + Object f4 = new InnerClass(null) { + <@A R> void method() { } + }; + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A { } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/MultipleTargets.java b/langtools/test/tools/javac/annotations/typeAnnotations/MultipleTargets.java new file mode 100644 index 00000000000..041366cd701 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/MultipleTargets.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6843077 8006775 + * @summary check that type annotations may appear on void method if it is a + * method annotation too. + * @author Mahmood Ali + * @compile MultipleTargets.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class TypeUseTarget { + @A void voidMethod() { } +} + +@Target({ElementType.TYPE_USE, ElementType.METHOD}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java new file mode 100644 index 00000000000..8ffa7e5b53c --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.util.*; +import java.io.*; + +/* + * @test + * @summary compiler accepts all values + * @author Mahmood Ali + * @author Yuri Gaevsky + * @compile TargetTypes.java + */ + +@Target({TYPE_USE, TYPE_PARAMETER, TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@interface A {} + +/** wildcard bound */ +class T0x1C { + void m0x1C(List lst) {} +} + +/** wildcard bound generic/array */ +class T0x1D { + void m0x1D(List> lst) {} +} + +/** typecast */ +class T0x00 { + void m0x00(Long l1) { + Object l2 = (@A Long) l1; + } +} + +/** typecast generic/array */ +class T0x01 { + void m0x01(List list) { + List l = (List<@A T>) list; + } +} + +/** instanceof */ +class T0x02 { + boolean m0x02(String s) { + return (s instanceof @A String); + } +} + +/** object creation (new) */ +class T0x04 { + void m0x04() { + new @A ArrayList(); + } +} + +/** local variable */ +class T0x08 { + void m0x08() { + @A String s = null; + } +} + +/** method parameter generic/array */ +class T0x0D { + void m0x0D(HashMap<@A Object, List<@A List<@A Class>>> s1) {} +} + +/** method receiver */ +class T0x06 { + void m0x06(@A T0x06 this) {} +} + +/** method return type generic/array */ +class T0x0B { + Class<@A Object> m0x0B() { return null; } +} + +/** field generic/array */ +class T0x0F { + HashMap<@A Object, @A Object> c1; +} + +/** method type parameter */ +class T0x20 { + <@A T, @A U> void m0x20() {} +} + +/** class type parameter */ +class T0x22<@A T, @A U> { +} + +/** class type parameter bound */ +class T0x10 { +} + +/** method type parameter bound */ +class T0x12 { + void m0x12() {} +} + +/** class type parameter bound generic/array */ +class T0x11> { +} + + +/** method type parameter bound generic/array */ +class T0x13 { + static > T m0x13() { + return null; + } +} + +/** class extends/implements generic/array */ +class T0x15 extends ArrayList<@A T> { +} + +/** type test (instanceof) generic/array */ +class T0x03 { + void m0x03(T typeObj, Object obj) { + boolean ok = obj instanceof String @A []; + } +} + +/** object creation (new) generic/array */ +class T0x05 { + void m0x05() { + new ArrayList<@A T>(); + } +} + +/** local variable generic/array */ +class T0x09 { + void g() { + List<@A String> l = null; + } + + void a() { + String @A [] as = null; + } +} + +/** type argument in constructor call generic/array */ +class T0x19 { + T0x19() {} + + void g() { + new > T0x19(); + } +} + +/** type argument in method call generic/array */ +class T0x1B { + void m0x1B() { + Collections.emptyList(); + } +} + +/** type argument in constructor call */ +class T0x18 { + T0x18() {} + + void m() { + new <@A Integer> T0x18(); + } +} + +/** type argument in method call */ +class T0x1A { + public static T m() { return null; } + static void m0x1A() { + T0x1A.<@A Integer, @A Short>m(); + } +} + +/** class extends/implements */ +class T0x14 extends @A Object implements @A Serializable, @A Cloneable { +} + +/** exception type in throws */ +class T0x16 { + void m0x16() throws @A Exception {} +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TypeParameterTarget.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeParameterTarget.java new file mode 100644 index 00000000000..100331c1090 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeParameterTarget.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6843077 8006775 + * @summary check that type annotations may appear on all type parameter + * @author Mahmood Ali + * @compile TypeParameterTarget.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class TypeUseTarget<@A K extends Object> { + String[] field; + + <@A K, @A V> String genericMethod(K k) { return null; } +} + +interface MyInterface { } + +@interface MyAnnotation { } + +@Target(ElementType.TYPE_PARAMETER) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java new file mode 100644 index 00000000000..31ec31adceb --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.*; +import java.util.Set; +import java.util.HashSet; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.lang.model.util.ElementFilter; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePath; +import com.sun.tools.javac.main.JavaCompiler; +import com.sun.tools.javac.main.JavaCompiler.CompileState; +import com.sun.tools.javac.processing.JavacProcessingEnvironment; +import com.sun.tools.javac.util.Context; + +/* + * @test + * @summary test that type processors are run when -proc:only is passed. + * This class implements the functionality of a type processor, as previously + * embodied by the AbstractTypeProcessor class. + * + * @author Mahmood Ali + * @author Werner Dietl + */ +@SupportedAnnotationTypes("*") +public class TypeProcOnly extends AbstractProcessor { + private static final String INDICATOR = "INDICATOR"; + + private final AttributionTaskListener listener = new AttributionTaskListener(); + private final Set elements = new HashSet(); + + @Override + public final void init(ProcessingEnvironment env) { + super.init(env); + JavacTask.instance(env).addTaskListener(listener); + Context ctx = ((JavacProcessingEnvironment)processingEnv).getContext(); + JavaCompiler compiler = JavaCompiler.instance(ctx); + compiler.shouldStopPolicyIfNoError = CompileState.max( + compiler.shouldStopPolicyIfNoError, + CompileState.FLOW); + } + + @Override + public final boolean process(Set annotations, + RoundEnvironment roundEnv) { + for (TypeElement elem : ElementFilter.typesIn(roundEnv.getRootElements())) { + elements.add(elem.getQualifiedName()); + } + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + private final class AttributionTaskListener implements TaskListener { + @Override + public void started(TaskEvent e) { } + + @Override + public void finished(TaskEvent e) { + if (e.getKind() != TaskEvent.Kind.ANALYZE) + return; + + if (!elements.remove(e.getTypeElement().getQualifiedName())) + return; + + System.out.println(INDICATOR); + } + } + + + private static File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("class Test { }"); + out.close(); + return f; + } + + public static void main(String[] args) throws Exception { + PrintStream prevOut = System.out; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(bytes); + System.setOut(out); + + try { + File f = writeTestFile(); + com.sun.tools.javac.Main.compile(new String[] {"-proc:only", "-processor", "TypeProcOnly", f.getAbsolutePath()}); + } finally { + System.setOut(prevOut); + } + + if (bytes.toString().trim().equals(INDICATOR)) { + System.out.println("PASSED"); + } else { + throw new Exception("Processor did not run correctly. Output: " + bytes); + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TypeUseTarget.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeUseTarget.java new file mode 100644 index 00000000000..4ec21c0ef2a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeUseTarget.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6843077 8006775 + * @summary check that type annotations may appear on all type declarations + * @author Mahmood Ali + * @compile TypeUseTarget.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@A +class TypeUseTarget { + @A String @A [] field; + + @A String test(@A TypeUseTarget this, @A String param, @A String @A ... vararg) { + @A Object o = new @A String @A [3]; + TypeUseTarget<@A String> target; + return (@A String) null; + } + + @A String genericMethod(K k) { return null; } + @Decl @A String genericMethod1(K k) { return null; } + @A @Decl String genericMethod2(K k) { return null; } + @Decl @A String genericMethod3(K k) { return null; } + @Decl String genericMethod4(K k) { return null; } + @A @Decl String genericMethod5(K k) { return null; } +} + +@A +interface MyInterface { } + +@A +@interface MyAnnotation { } + +@Target(ElementType.TYPE_USE) +@interface A { } + +@interface Decl { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java new file mode 100644 index 00000000000..68f11f5e64c --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 Checks the annotation types targeting array types + */ + +import com.sun.tools.javac.api.JavacTool; +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.lang.annotation.*; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import com.sun.source.tree.*; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import javax.tools.StandardJavaFileManager; + + +public class AnnotatedArrayOrder { + public static void main(String[] args) throws Exception { + PrintWriter out = new PrintWriter(System.out, true); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + File testSrc = new File(System.getProperty("test.src")); + Iterable f = + fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, "AnnotatedArrayOrder.java"))); + JavacTask task = tool.getTask(out, fm, null, null, null, f); + Iterable trees = task.parse(); + out.flush(); + + Scanner s = new Scanner(); + for (CompilationUnitTree t: trees) + s.scan(t, null); + + } + + private static class Scanner extends TreeScanner { + public Void visitCompilationUnit(CompilationUnitTree node, Void ignore) { + super.visitCompilationUnit(node, ignore); + if (!expectedLocations.isEmpty()) { + throw new AssertionError("Didn't found all annotations: " + expectedLocations); + } + return null; + } + + private void testAnnotations(List annos, int found) { + String annotation = annos.get(0).toString(); + + if (!expectedLocations.containsKey(annotation)) + throw new AssertionError("Found unexpected annotation: " + annotation + expectedLocations); + + int expected = expectedLocations.get(annotation); + if (found != expected) + throw new AssertionError("The expected array length for this error doesn't match"); + + expectedLocations.remove(annotation); + } + + public Void visitAnnotatedType(AnnotatedTypeTree node, Void ignore) { + testAnnotations(node.getAnnotations(), arrayLength(node)); + return super.visitAnnotatedType(node, ignore); + } + + private int arrayLength(Tree tree) { + switch (tree.getKind()) { + case ARRAY_TYPE: + return 1 + arrayLength(((ArrayTypeTree)tree).getType()); + case ANNOTATED_TYPE: + return arrayLength(((AnnotatedTypeTree)tree).getUnderlyingType()); + default: + return 0; + } + } + } + + // expectedLocations values: + static Map expectedLocations = new HashMap(); + + // visited code + @A String @C [] @B [] field; + static { + // Shouldn't find @A(), as it is field annotation + expectedLocations.put("@B()", 1); + expectedLocations.put("@C()", 2); + } + + List<@D String @F [] @E []> typearg; + static { + expectedLocations.put("@D()", 0); + expectedLocations.put("@E()", 1); + expectedLocations.put("@F()", 2); + } + + void varargSimple(@G String @H ... vararg1) { } + static { + // Shouldn't find @G(), as it is a parameter annotation + expectedLocations.put("@H()", 1); + } + + void varargLong(@I String @L [] @K [] @J ... vararg2) { } + static { + // Shouldn't find @I(), as it is a parameter annotation + expectedLocations.put("@J()", 1); + expectedLocations.put("@K()", 2); + expectedLocations.put("@L()", 3); + } + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface B {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface C {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface D {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface E {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface F {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface G {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface H {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface I {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface J {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface K {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface L {} +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java new file mode 100644 index 00000000000..952f37c2b92 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 Checks that the interaction between annotated and unannotated + * array levels in array creation trees + */ + +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.tree.JCTree.JCNewArray; +import java.lang.annotation.*; +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import com.sun.source.tree.*; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import javax.tools.StandardJavaFileManager; + + +public class ArrayCreationTree { + public static void main(String[] args) throws Exception { + PrintWriter out = new PrintWriter(System.out, true); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + File testSrc = new File(System.getProperty("test.src")); + Iterable f = + fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, "ArrayCreationTree.java"))); + JavacTask task = tool.getTask(out, fm, null, null, null, f); + Iterable trees = task.parse(); + out.flush(); + + Scanner s = new Scanner(); + for (CompilationUnitTree t: trees) + s.scan(t, null); + + } + + private static class Scanner extends TreeScanner { + int foundAnnotations = 0; + public Void visitCompilationUnit(CompilationUnitTree node, Void ignore) { + super.visitCompilationUnit(node, ignore); + if (foundAnnotations != expectedAnnotations) { + throw new AssertionError("Expected " + expectedAnnotations + + " annotations but found: " + foundAnnotations); + } + return null; + } + + private void testAnnotations(List annos, int found) { + if (annos.isEmpty()) return; + + String annotation = annos.get(0).toString(); + foundAnnotations++; + + int expected = -1; + if (annotation.equals("@A()")) + expected = 0; + else if (annotation.equals("@B()")) + expected = 1; + else if (annotation.equals("@C()")) + expected = 2; + else + throw new AssertionError("found an unexpected annotation: " + annotation); + if (found != expected) { + throw new AssertionError("Unexpected found length" + + ", found " + found + " but expected " + expected); + } + } + + public Void visitAnnotatedType(AnnotatedTypeTree node, Void ignore) { + testAnnotations(node.getAnnotations(), arrayLength(node)); + return super.visitAnnotatedType(node, ignore); + } + + public Void visitNewArray(NewArrayTree node, Void ignore) { + // the Tree API hasn't been updated to expose annotations yet + JCNewArray newArray = (JCNewArray)node; + int totalLength = node.getDimensions().size() + + arrayLength(node.getType()) + + ((newArray.getInitializers() != null) ? 1 : 0); + testAnnotations(newArray.annotations, totalLength); + int count = 0; + for (List annos : newArray.dimAnnotations) { + testAnnotations(annos, totalLength - count); + count++; + } + return super.visitNewArray(node, ignore); + } + + private int arrayLength(Tree tree) { + // TODO: the tree is null when called with node.getType(). Why? + if (tree==null) return -1; + switch (tree.getKind()) { + case ARRAY_TYPE: + return 1 + arrayLength(((ArrayTypeTree)tree).getType()); + case ANNOTATED_TYPE: + return arrayLength(((AnnotatedTypeTree)tree).getUnderlyingType()); + default: + return 0; + } + } + } + + static int expectedAnnotations = 21; + + Object a1 = new @A Object @C [2] @B [1]; + Object b1 = new @A Object @C [2] @B [ ]; + Object c1 = new @A Object @C [ ] @B [ ] { }; + + Object a2 = new @A Object @C [2] [1]; + Object b2 = new @A Object @C [2] [ ]; + Object c2 = new @A Object @C [ ] [ ] { }; + + Object a3 = new @A Object [2] @B [1]; + Object b3 = new @A Object [2] @B [ ]; + Object c3 = new @A Object [ ] @B [ ] { }; + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface B {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface C {} + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java new file mode 100644 index 00000000000..1b73d918a03 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 Checks that the interaction between annotated and unannotated + * array levels + */ + +import com.sun.tools.javac.api.JavacTool; +import java.lang.annotation.*; +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import com.sun.source.tree.*; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import javax.tools.StandardJavaFileManager; + + +public class ArrayPositionConsistency { + public static void main(String[] args) throws Exception { + PrintWriter out = new PrintWriter(System.out, true); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + File testSrc = new File(System.getProperty("test.src")); + Iterable f = + fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, "ArrayPositionConsistency.java"))); + JavacTask task = tool.getTask(out, fm, null, null, null, f); + Iterable trees = task.parse(); + out.flush(); + + Scanner s = new Scanner(); + for (CompilationUnitTree t: trees) + s.scan(t, null); + + } + + private static class Scanner extends TreeScanner { + int foundAnnotations = 0; + public Void visitCompilationUnit(CompilationUnitTree node, Void ignore) { + super.visitCompilationUnit(node, ignore); + if (foundAnnotations != expectedAnnotations) { + throw new AssertionError("Expected " + expectedAnnotations + + " annotations but found: " + foundAnnotations); + } + return null; + } + + private void testAnnotations(List annos, int found) { + String annotation = annos.get(0).toString(); + foundAnnotations++; + + int expected = -1; + if (annotation.equals("@A()")) + expected = 0; + else if (annotation.equals("@B()")) + expected = 1; + else if (annotation.equals("@C()")) + expected = 2; + else + throw new AssertionError("found an unexpected annotation: " + annotation); + if (found != expected) { + throw new AssertionError("Unexpected found length" + + ", found " + found + " but expected " + expected); + } + } + + public Void visitAnnotatedType(AnnotatedTypeTree node, Void ignore) { + testAnnotations(node.getAnnotations(), arrayLength(node)); + return super.visitAnnotatedType(node, ignore); + } + + private int arrayLength(Tree tree) { + switch (tree.getKind()) { + case ARRAY_TYPE: + return 1 + arrayLength(((ArrayTypeTree)tree).getType()); + case ANNOTATED_TYPE: + return arrayLength(((AnnotatedTypeTree)tree).getUnderlyingType()); + default: + return 0; + } + } + } + + static int expectedAnnotations = 23; + + // visited code + @A String @C [] @B [] field1; + @A String @C [] [] field2; + @A String [] @B [] field3; + String [] @B [] field4; + + @A List @C [] @B [] genfield1; + @A List @C [] [] genfield2; + @A List [] @B [] genfield3; + List [] @B [] genfield4; + + List<@A String @C [] @B []> typearg1; + List<@A String @C [] []> typearg2; + List<@A String [] @B []> typearg3; + List< String [] @B []> typearg4; + + void vararg1(@A String @C [] @B ... arg) {} + void vararg2(@A String @C [] ... arg) {} + void vararg3(@A String [] @B ... arg) {} + void vararg4( String [] @B ... arg) {} + + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface B {} + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface C {} + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/attribution/Scopes.java b/langtools/test/tools/javac/annotations/typeAnnotations/attribution/Scopes.java new file mode 100644 index 00000000000..da01c38d096 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/attribution/Scopes.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6843077 8006775 + * @summary test scopes of attribution + * @author Mahmood Ali + * @compile Scopes.java + */ +class Scopes { + + void test(@A(VALUE) Scopes this) { } + void test1(@A(value=VALUE) Scopes this) { } + + private static final int VALUE = 1; + @interface A { int value(); } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java new file mode 100644 index 00000000000..b02621639aa --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2012, 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.lang.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +public class ClassfileTestHelper { + int expected_tinvisibles = 0; + int expected_tvisibles = 0; + int expected_invisibles = 0; + int expected_visibles = 0; + + //Makes debugging much easier. Set to 'false' for less output. + public Boolean verbose = true; + void println(String msg) { if(verbose) System.out.println(msg); } + + File writeTestFile(String fname, String source) throws IOException { + File f = new File(fname); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println(source); + out.close(); + return f; + } + + File compile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { + "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + ClassFile getClassFile(String name) throws IOException, ConstantPoolException { + URL url = getClass().getResource(name); + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + ClassFile getClassFile(URL url) throws IOException, ConstantPoolException { + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + /************ Helper annotations counting methods ******************/ + void test(ClassFile cf) { + test("CLASS",cf, null, null, Attribute.RuntimeVisibleTypeAnnotations, true); + test("CLASS",cf, null, null, Attribute.RuntimeInvisibleTypeAnnotations, false); + //RuntimeAnnotations since one annotation can result in two attributes. + test("CLASS",cf, null, null, Attribute.RuntimeVisibleAnnotations, true); + test("CLASS",cf, null, null, Attribute.RuntimeInvisibleAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test("METHOD",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test("METHOD",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + test("METHOD",cf, null, m, Attribute.RuntimeVisibleAnnotations, true); + test("METHOD",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false); + } + + void test(ClassFile cf, Field f) { + test("FIELD",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true); + test("FIELD",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false); + test("FIELD",cf, f, null, Attribute.RuntimeVisibleAnnotations, true); + test("FIELD",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false); + } + + + // Test the result of Attributes.getIndex according to expectations + // encoded in the class/field/method name; increment annotations counts. + void test(String ttype, ClassFile cf, Field f, Method m, String annName, boolean visible) { + String testtype = ttype; + String name = null; + int index = -1; + Attribute attr = null; + boolean isTAattr = annName.contains("TypeAnnotations"); + try { + switch(testtype) { + case "FIELD": + name = f.getName(cf.constant_pool); + index = f.attributes.getIndex(cf.constant_pool, annName); + if(index!= -1) attr = f.attributes.get(index); + break; + case "METHOD": + name = m.getName(cf.constant_pool); + index = m.attributes.getIndex(cf.constant_pool, annName); + if(index!= -1) attr = m.attributes.get(index); + break; + default: + name = cf.getName(); + index = cf.attributes.getIndex(cf.constant_pool, annName); + if(index!= -1) attr = cf.attributes.get(index); + } + } catch(ConstantPoolException cpe) { cpe.printStackTrace(); } + + if (index != -1) { + assert attr instanceof RuntimeTypeAnnotations_attribute; + if(isTAattr) { //count RuntimeTypeAnnotations + RuntimeTypeAnnotations_attribute tAttr = + (RuntimeTypeAnnotations_attribute)attr; + println(testtype + ": " + name + ", " + annName + ": " + + tAttr.annotations.length ); + allt += tAttr.annotations.length; + if (visible) + tvisibles += tAttr.annotations.length; + else + tinvisibles += tAttr.annotations.length; + } else { + RuntimeAnnotations_attribute tAttr = + (RuntimeAnnotations_attribute)attr; + println(testtype + ": " + name + ", " + annName + ": " + + tAttr.annotations.length ); + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + } + + void countAnnotations() { + errors=0; + int expected_allt = expected_tvisibles + expected_tinvisibles; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_allt != allt) { + errors++; + System.err.println("Failure: expected " + expected_allt + + " type annotations but found " + allt); + } + if (expected_all != all) { + errors++; + System.err.println("Failure: expected " + expected_all + + " annotations but found " + all); + } + if (expected_tvisibles != tvisibles) { + errors++; + System.err.println("Failure: expected " + expected_tvisibles + + " typevisible annotations but found " + tvisibles); + } + + if (expected_tinvisibles != tinvisibles) { + errors++; + System.err.println("Failure: expected " + expected_tinvisibles + + " typeinvisible annotations but found " + tinvisibles); + } + allt=0; + tvisibles=0; + tinvisibles=0; + all=0; + visibles=0; + invisibles=0; + } + + int errors; + int allt; + int tvisibles; + int tinvisibles; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java new file mode 100644 index 00000000000..ed3c094685c --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java @@ -0,0 +1,366 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8005085 8005877 8004829 8005681 8006734 8006775 + * @ignore + * @summary Combinations of Target ElementTypes on (repeated)type annotations. + */ + +import com.sun.tools.classfile.*; +import java.io.File; + +public class CombinationsTargetTest1 extends ClassfileTestHelper { + // Helps identify test case in event of failure. + int testcount = 0; + int src1 = 1, src2 = 2, src4 = 4, + src5 = 5, src6 = 6, src7 = 7; + + String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR", + "LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"}; + + // local class tests will have an inner class. + Boolean hasInnerClass=false; + String innerClassname=""; + + public static void main(String[] args) throws Exception { + new CombinationsTargetTest1().run(); + } + + void run() throws Exception { + // Determines which repeat and order in source(ABMix). + Boolean As= false, BDs=true, ABMix=false; + int testrun=0; + // A repeats and/or B/D repeats, ABMix for order of As and Bs. + Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats + {true,false,false}, //repeat @A + {false,true,false}, //repeat @B + {true,true,false}, //repeat both + {false,false,true} //repeat mix + }; + for(Boolean[] bCombo : bRepeat) { + As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2]; + for(String et : ETypes) { + switch(et) { + case "METHOD": + test( 8, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1); + test(10, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src2); + test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src4); + test(10, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src6); + test( 0, 8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1); + test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src2); + test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src4); + test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src6); + break; + case "CONSTRUCTOR": + case "FIELD": + test( 8, 0, 4, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1); + test( 6, 0, 3, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src5); + test( 9, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src7); + test( 0, 8, 0, 4, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1); + test( 0, 6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, src5); + test( 0, 9, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src7); + break; + default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/ + test( 8, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1); + test( 6, 0, 3, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src5); + test( 0, 8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1); + test( 0, 6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, src5); + } + } + } + } + + public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats, + Boolean BDrepeats, Boolean ABmix, String rtn, String et2, + Integer N, int source) throws Exception { + ++testcount; + expected_tvisibles = tvis; + expected_tinvisibles = tinv; + expected_visibles = vis; + expected_invisibles = inv; + File testFile = null; + String tname="Test" + N.toString(); + hasInnerClass=false; + String testDef = "Test " + testcount + " parameters: tinv=" + tinv + + ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis + + ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats + + ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " + + et2 + ", src=" + source; + + println(testDef); + // Create test source and File. + String sourceString = sourceString(tname, rtn, et2, Arepeats, + BDrepeats, ABmix, source); + testFile = writeTestFile(tname+".java", sourceString); + // Compile test source and read classfile. + File classFile = null; + try { + classFile = compile(testFile); + } catch (Error err) { + System.err.println("Failed compile. Source:\n" + sourceString); + throw err; + } + //if sourcString() set hasInnerClass it also set innerClassname. + if(hasInnerClass) { + StringBuffer sb = new StringBuffer(classFile.getAbsolutePath()); + classFile=new File(sb.insert(sb.lastIndexOf(".class"),innerClassname).toString()); + } + ClassFile cf = ClassFile.read(classFile); + + //Test class,fields and method counts. + test(cf); + + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + countAnnotations(); + if (errors > 0) { + System.err.println( testDef ); + System.err.println( "Source:\n" + sourceString ); + throw new Exception( errors + " errors found" ); + } + println("Pass"); + } + + // + // Source for test cases + // + String sourceString(String testname, String retentn, String annot2, + Boolean Arepeats, Boolean BDrepeats, Boolean ABmix, + int src) { + + String As = "@A", Bs = "@B", Ds = "@D"; + if(Arepeats) As = "@A @A"; + if(BDrepeats) { + Bs = "@B @B"; + Ds = "@D @D"; + } + if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; } + + // Source to check for TYPE_USE and TYPE_PARAMETER annotations. + // Source base (annotations) is same for all test cases. + String source = new String(); + String imports = new String("import java.lang.annotation.*; \n" + + "import static java.lang.annotation.RetentionPolicy.*; \n" + + "import static java.lang.annotation.ElementType.*; \n" + + "import java.util.List; \n" + + "import java.util.HashMap; \n" + + "import java.util.Map; \n\n"); + + String sourceBase = new String("@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@Repeatable( AC.class )\n" + + "@interface A { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@interface AC { A[] value(); }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@Repeatable( BC.class )\n" + + "@interface B { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@interface BC { B[] value(); } \n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_PARAMETER,_OTHER_})\n" + + "@interface C { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + + "@Repeatable(DC.class)\n" + + "@interface D { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + + "@interface DC { D[] value(); }\n\n"); + + // Test case sources with sample generated source. + switch(src) { + case 1: // repeating type annotations at class level + /* + * @A @B class Test1 { + * @A @B Test1(){} + * @A @B Integer i1 = 0; + * String @A @B [] @A @B [] sa = null; + * // type usage in method body + * String test(Test1 this, String param, String ... vararg) { + * Object o = new String [3]; + * return (String) null; + * }} + */ + source = new String( + "// (repeating) type annotations at class level. \n" + + "_As_ _Bs_ class " + testname + " {\n" + + "_As_ _Bs_ " + testname +"(){} \n" + + "_As_ _Bs_ Integer i1 = 0; \n" + + "String _As_ _Bs_ [] _As_ _Bs_ [] sa = null; \n" + + "// type usage in method body \n" + + "String test("+testname+" this, " + + "String param, String ... vararg) { \n" + + " Object o = new String [3]; \n" + + " return (String) null; \n" + + "} \n" + + "} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + + "\n\n"; + break; + case 2: // (repeating) type annotations on method. + /* + * class Test12 { + * Test12(){} + * // type usage on method + * @A @B String test(@A @B Test12 this, @A @B String param, @A @B String @A @B ... vararg) { + * Object o = new String [3]; + * return (String) null; + * }} + */ + source = new String( + "// (repeating) type annotations on method. \n" + + "class " + testname + " {\n" + + testname +"(){} \n" + + "// type usage on method \n" + + "_As_ _Bs_ String test(_As_ _Bs_ "+testname+" this, " + + "_As_ _Bs_ String param, _As_ _Bs_ String _As_ _Bs_ ... vararg) { \n" + + " Object o = new String [3]; \n" + + " return (String) null; \n" + + "} \n" + + "} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + + "\n\n"; + break; + case 4: //(repeating) annotations on wildcard, type arguments in anonymous class. + /* + * class Test13 { + * public T data = null; + * T getData() { return data;} + * String mtest( Test13 t){ return t.getData(); } + * public void test() { + * mtest( new Test13<@A @B String>() { + * void m1(List<@A @B ? extends @A @B Object> lst) {} + * void m2() throws@A @B Exception { } + * }); + * } + * } + */ + source = new String( source + + "// (repeating) annotations on wildcard, type arguments in anonymous class. \n" + + "class " + testname + " {\n" + + " public T data = null;\n" + + " T getData() { return data;}\n" + + " String mtest( " + testname + " t){ return t.getData(); }\n" + + " public void test() {\n" + + " mtest( new " + testname + "<_As_ _Bs_ String>() {\n" + + " void m1(List<_As_ _Bs_ ? extends _As_ _Bs_ Object> lst) {}\n" + + " void m2() throws_As_ _Bs_ Exception { }\n" + + " });\n" + + " }\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + "\n\n"; + hasInnerClass=true; + innerClassname="$1"; + break; + case 5: // (repeating)annotations on type parameters, bounds and type arguments on class decl. + /* + * @A @B @D + * class Test2<@A @B @C @D T extends @A @B Object> { + * Map, Integer> map = + * new HashMap, Integer>(); + * Map,Integer> map2 = new HashMap<>(); + * String test(Test2 this) { return null;} + * String genericMethod(T t) { return null; } + * } + */ + source = new String( source + + "// (repeating)annotations on type parameters, bounds and type arguments on class decl. \n" + + "_As_ _Bs_ _Ds_\n" + //8004829: A and B on type parameter below. + "class " + testname + "<_As_ _Bs_ @C _Ds_ T extends _As_ _Bs_ Object> {\n" + + " Map, Integer> map =\n" + + " new HashMap, Integer>();\n" + + " Map,Integer> map2 = new HashMap<>();\n" + + " String test(" + testname + " this) { return null;}\n" + + " String genericMethod(T t) { return null; }\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + + "\n\n"; + break; + case 6: // (repeating) annotations on type parameters, bounds and type arguments on method. + /* + * class Test14 { + * Map, Integer> map = + * new HashMap, Integer>(); + * Map, Integer> map2 = new HashMap<>(); + * String test(@A @B Test14<@D T> this) { return null;} + * <@C @D T> @A @B String genericMethod(@A @B @D T t) { return null; } + * } + */ + source = new String( source + + "// (repeating) annotations on type parameters, bounds and type arguments on method. \n" + + "class " + testname + " {\n" + + " Map, Integer> map =\n" + + " new HashMap, Integer>();\n" + + " Map, Integer> map2 = new HashMap<>();\n" + + " String test(_As_ _Bs_ " + testname + "<_Ds_ T> this) { return null;}\n" + + " <@C _Ds_ T> _As_ _Bs_ String genericMethod(_As_ _Bs_ _Ds_ T t) { return null; }\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + + "\n\n"; + break; + case 7: // repeating annotations on type parameters, bounds and type arguments in method. + /* + * class Test7{ + * Map, E > foo(E e) { + * class maptest <@A @B @D E> { + * Map,@A @B @D E> getMap() { + * return new HashMap,E>(); + * } + * } + * return new maptest().getMap(); + * } + * Map,String> shm = foo(new String("hello")); + * } + */ + source = new String( source + + "// (repeating)annotations on type parameters of class, method return value in method. \n" + + "class "+ testname + "{\n" + + " Map, E > foo(E e) {\n" + + " class maptest <_As_ _Bs_ _Ds_ E> {\n" + // inner class $1maptest + " Map,_As_ _Bs_ _Ds_ E> getMap() { \n" + + " return new HashMap,E>();\n" + + " }\n" + + " }\n" + + " return new maptest().getMap();\n" + + " }\n" + + " Map,String> shm = foo(new String(\"hello\"));\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + + "\n\n"; + hasInnerClass=true; + innerClassname="$1maptest"; + break; + } + return imports + source; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java new file mode 100644 index 00000000000..e3414db9f98 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java @@ -0,0 +1,282 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8005085 8005877 8004829 8005681 8006734 8006775 + * @ignore + * @summary Combinations of Target ElementTypes on (repeated)type annotations. + */ + +import com.sun.tools.classfile.*; +import java.io.File; + +public class CombinationsTargetTest2 extends ClassfileTestHelper { + // Helps identify test case in event of failure. + int testcount = 0; + int src3 = 3, src8 = 8, src9 = 9; + + String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR", + "LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"}; + + // local class tests will have an inner class. + Boolean hasInnerClass=false; + String innerClassname=""; + + public static void main(String[] args) throws Exception { + new CombinationsTargetTest2().run(); + } + + void run() throws Exception { + // Determines which repeat and order in source(ABMix). + Boolean As= false, BDs=true, ABMix=false; + int testrun=0; + // A repeats and/or B/D repeats, ABMix for order of As and Bs. + Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats + {true,false,false}, //repeat @A + {false,true,false}, //repeat @B + {true,true,false}, //repeat both + {false,false,true} //repeat mix + }; + for(Boolean[] bCombo : bRepeat) { + As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2]; + for(String et : ETypes) { + switch(et) { + case "METHOD": + test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src3); + test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src3); + break; + case "CONSTRUCTOR": + case "FIELD": + test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src3); + test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src8); + test( 6, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src9); + test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src3); + test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src8); + test( 0, 6, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src9); + break; + default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/ + break; + } + } + } + } + + public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats, + Boolean BDrepeats, Boolean ABmix, String rtn, String et2, + Integer N, int source) throws Exception { + ++testcount; + expected_tvisibles = tvis; + expected_tinvisibles = tinv; + expected_visibles = vis; + expected_invisibles = inv; + File testFile = null; + String tname="Test" + N.toString(); + hasInnerClass=false; + String testDef = "Test " + testcount + " parameters: tinv=" + tinv + + ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis + + ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats + + ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " + + et2 + ", src=" + source; + +// Uncomment this block to run the tests but skip failing scenarios. +// // 8005681 - skip cases with repeated annotations on new, array, cast. +// if((source==3 || source==8 || source==9) && (ABmix || (Arepeats && BDrepeats))) { +// System.out.println(testDef+"\n8005681-skip repeated annotations on new,array,cast"); +// return; +// } + + println(testDef); + // Create test source and File. + String sourceString = sourceString(tname, rtn, et2, Arepeats, + BDrepeats, ABmix, source); + testFile = writeTestFile(tname+".java", sourceString); + // Compile test source and read classfile. + File classFile = null; + try { + classFile = compile(testFile); + } catch (Error err) { + System.err.println("Failed compile. Source:\n" + sourceString); + throw err; + } + //if sourcString() set hasInnerClass it also set innerClassname. + if(hasInnerClass) { + StringBuffer sb = new StringBuffer(classFile.getAbsolutePath()); + classFile=new File(sb.insert(sb.lastIndexOf(".class"),innerClassname).toString()); + } + ClassFile cf = ClassFile.read(classFile); + + //Test class,fields and method counts. + test(cf); + + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + countAnnotations(); + if (errors > 0) { + System.err.println( testDef ); + System.err.println( "Source:\n" + sourceString ); + throw new Exception( errors + " errors found" ); + } + println("Pass"); + } + + // + // Source for test cases + // + String sourceString(String testname, String retentn, String annot2, + Boolean Arepeats, Boolean BDrepeats, Boolean ABmix, + int src) { + + String As = "@A", Bs = "@B", Ds = "@D"; + if(Arepeats) As = "@A @A"; + if(BDrepeats) { + Bs = "@B @B"; + Ds = "@D @D"; + } + if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; } + + // Source to check for TYPE_USE and TYPE_PARAMETER annotations. + // Source base (annotations) is same for all test cases. + String source = new String(); + String imports = new String("import java.lang.annotation.*; \n" + + "import static java.lang.annotation.RetentionPolicy.*; \n" + + "import static java.lang.annotation.ElementType.*; \n" + + "import java.util.List; \n" + + "import java.util.HashMap; \n" + + "import java.util.Map; \n\n"); + + String sourceBase = new String("@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@Repeatable( AC.class )\n" + + "@interface A { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@interface AC { A[] value(); }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@Repeatable( BC.class )\n" + + "@interface B { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,_OTHER_})\n" + + "@interface BC { B[] value(); } \n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + + "@Repeatable(DC.class)\n" + + "@interface D { }\n\n" + + + "@Retention("+retentn+")\n" + + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + + "@interface DC { D[] value(); }\n\n"); + + // Test case sources with sample generated source + switch(src) { + case 3: // (repeating) type annotations on field in method body + /* + * class Test1 { + * Test1(){} + * // type usage in method body + * String test(Test1 this, String param, String ... vararg) { + * @A @B + * Object o = new @A @B String @A @B [3]; + * return (@A @B String) null; + * }} + */ + source = new String( + "class " + testname + " {\n" + + "" + testname +"(){} \n" + + "// type usage in method body \n" + + "String test("+testname+" this, " + + "String param, String ... vararg) { \n" + + " _As_ _Bs_\n Object o = new _As_ _Bs_ String _As_ _Bs_ [3]; \n" + + " return (_As_ _Bs_ String) null; \n" + + "} \n" + + "} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + + "\n\n"; + break; + case 8: // (repeating) annotations on type parameters, bounds and type arguments in new statement. + /* + * class Test2 { + * Map, Integer> map = + * new HashMap<@A @B List<@A @B String>, @A @B Integer>(); + * Map, Integer> map2 = new @A @B HashMap<>(); + * String test(Test2 this) { return null;} + * String genericMethod(T t) { return null; } + * } + */ + source = new String( source + + "// (repeating) annotations on type parameters, bounds and type arguments. \n" + + "class " + testname + " {\n" + + " Map, Integer> map =\n" + + " new HashMap<_As_ _Bs_ List<_As_ _Bs_ String>, _As_ _Bs_ Integer>();\n" + + " Map, Integer> map2 = new _As_ _Bs_ HashMap<>();\n" + + " String test(" + testname + " this) { return null;}\n" + + " String genericMethod(T t) { return null; }\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + + "\n\n"; + break; + case 9: // (repeating)annotations on type parameters of class, method return value in method. + /* + * class Test3{ + * Map, E > foo(E e) { + * class maptest { + * Map,E> getMap() { + * Map,E> Em = new HashMap,@A @B @D E>(); + * return Em; + * } + * } + * return new maptest().getMap(); + * } + * Map,String> shm = foo(new String("hello")); + * } + */ + source = new String( source + + "// (repeating)annotations on type parameters of class, method return value in method. \n" + + "class "+ testname + "{\n" + + " Map, E > foo(E e) {\n" + + " class maptest {\n" + // inner class $1maptest + " Map,E> getMap() { \n" + + " Map,E> Em = new HashMap,_As_ _Bs_ _Ds_ E>();\n" + + " return Em;\n" + + " }\n" + + " }\n" + + " return new maptest().getMap();\n" + + " }\n" + + " Map,String> shm = foo(new String(\"hello\"));\n" + + "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + + "\n\n"; + hasInnerClass=true; + innerClassname="$1maptest"; + break; + + } + return imports + source; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/DeadCode.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/DeadCode.java new file mode 100644 index 00000000000..6d00bcc2ce6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/DeadCode.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009, 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.lang.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 6917130 8006775 + * @summary test that optimized away annotations are not emited to classfile + */ + +public class DeadCode extends ClassfileTestHelper { + public static void main(String[] args) throws Exception { + new DeadCode().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 1; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("DeadCode$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + + void test() { + List o = null; + o.toString(); + + @A String m; + if (false) { + @A String a; + @A String b = "m"; + b.toString(); + List c = null; + c.toString(); + } + } + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java new file mode 100644 index 00000000000..f39857cada1 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test ClassLiterals + * @summary test that new type arguments are emitted to classfile + */ + +public class NewTypeArguments extends ClassfileTestHelper{ + public static void main(String[] args) throws Exception { + new NewTypeArguments().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 3; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("NewTypeArguments$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + Test(E e) {} + + void test() { + new <@A String> Test(null); + new <@A List<@A String>> Test(null); + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java new file mode 100644 index 00000000000..a5dc098811b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.*; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test NoTargetAnnotations + * @summary test that annotations with no Target meta type is emitted + * only once as declaration annotation + */ +public class NoTargetAnnotations { + + public static void main(String[] args) throws Exception { + new NoTargetAnnotations().run(); + } + + public void run() throws Exception { + ClassFile cf = getClassFile("NoTargetAnnotations$Test.class"); + for (Field f : cf.fields) { + test(cf, f); + testDeclaration(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + testDeclaration(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + ClassFile getClassFile(String name) throws IOException, ConstantPoolException { + URL url = getClass().getResource(name); + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + /************ Helper annotations counting methods ******************/ + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void testDeclaration(ClassFile cf, Method m) { + testDecl(cf, m, Attribute.RuntimeVisibleAnnotations, true); + testDecl(cf, m, Attribute.RuntimeInvisibleAnnotations, false); + } + + void testDeclaration(ClassFile cf, Field m) { + testDecl(cf, m, Attribute.RuntimeVisibleAnnotations, true); + testDecl(cf, m, Attribute.RuntimeInvisibleAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void testDecl(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeAnnotations_attribute; + RuntimeAnnotations_attribute tAttr = (RuntimeAnnotations_attribute)attr; + this.declAnnotations += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void testDecl(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeAnnotations_attribute; + RuntimeAnnotations_attribute tAttr = (RuntimeAnnotations_attribute)attr; + this.declAnnotations += tAttr.annotations.length; + } + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-XDTA:writer", "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + if (expected_decl != declAnnotations) { + errors++; + System.err.println("expected " + expected_decl + + " declaration annotations but found " + declAnnotations); + } + } + + int errors; + int all; + int visibles; + int invisibles; + + int declAnnotations; + + /*********************** Test class *************************/ + static int expected_invisibles = 0; + static int expected_visibles = 0; + static int expected_decl = 1; + + static class Test { + @Retention(RetentionPolicy.RUNTIME) + @interface A {} + + @A String method() { + return null; + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java new file mode 100644 index 00000000000..5529fa5a664 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary test that typecasts annotation are emitted if only the cast + * expression is optimized away + */ + +public class TypeCasts extends ClassfileTestHelper{ + public static void main(String[] args) throws Exception { + new TypeCasts().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 4; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("TypeCasts$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + + void emit() { + Object o = null; + String s = null; + + String a0 = (@A String)o; + Object a1 = (@A Object)o; + + String b0 = (@A String)s; + Object b1 = (@A Object)s; + } + + void alldeadcode() { + Object o = null; + + if (false) { + String a0 = (@A String)o; + } + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java new file mode 100644 index 00000000000..e0301520d74 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/* + * @test Wildcards + * @bug 6843077 8006775 + * @summary test that annotations target wildcards get emitted to classfile + */ +public class Wildcards extends ClassfileTestHelper { + public static void main(String[] args) throws Exception { + new Wildcards().run(); + } + + public void run() throws Exception { + expected_tinvisibles = 3; + expected_tvisibles = 0; + + ClassFile cf = getClassFile("Wildcards$Test.class"); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + /*********************** Test class *************************/ + static class Test { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A {} + + List f; + + List test(List p) { + List l; // not counted... gets optimized away + return null; + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.java new file mode 100644 index 00000000000..db14aefee15 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary Import clauses cannot use annotations. + * @author Werner Dietl + * @compile/fail/ref=AnnotatedImport.out -XDrawDiagnostics AnnotatedImport.java + */ + +import java.@A util.List; +import @A java.util.Map; +import java.util.@A HashMap; + +class AnnotatedImport { } + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out new file mode 100644 index 00000000000..dbd0d42c1e3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedImport.out @@ -0,0 +1,7 @@ +AnnotatedImport.java:9:13: compiler.err.expected: token.identifier +AnnotatedImport.java:9:14: compiler.err.expected3: class, interface, enum +AnnotatedImport.java:10:7: compiler.err.expected: token.identifier +AnnotatedImport.java:10:10: compiler.err.expected: ';' +AnnotatedImport.java:11:18: compiler.err.expected: token.identifier +AnnotatedImport.java:11:19: compiler.err.expected3: class, interface, enum +6 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.java new file mode 100644 index 00000000000..6b8b64a656f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary Package declarations cannot use annotations. + * @author Werner Dietl + * @compile/fail/ref=AnnotatedPackage1.out -XDrawDiagnostics AnnotatedPackage1.java + */ + +package name.@A p1.p2; + +class AnnotatedPackage1 { } + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out new file mode 100644 index 00000000000..66ae60f72f2 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage1.out @@ -0,0 +1,3 @@ +AnnotatedPackage1.java:9:14: compiler.err.expected: token.identifier +AnnotatedPackage1.java:9:15: compiler.err.expected3: class, interface, enum +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.java new file mode 100644 index 00000000000..53eb5b142f3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary Package declarations cannot use annotations. + * @author Werner Dietl + * @compile/fail/ref=AnnotatedPackage2.out -XDrawDiagnostics AnnotatedPackage2.java + */ + +package @A p1.p2; + +class AnnotatedPackage2 { } + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out new file mode 100644 index 00000000000..2ab804500f8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out @@ -0,0 +1,3 @@ +AnnotatedPackage2.java:9:8: compiler.err.expected: token.identifier +AnnotatedPackage2.java:9:10: compiler.err.expected3: class, interface, enum +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.java new file mode 100644 index 00000000000..9f80b2e9f28 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test that only Java 8 allows type annotations + * @author Mahmood Ali + * @compile/fail/ref=AnnotationVersion.out -XDrawDiagnostics -Xlint:-options -source 1.6 AnnotationVersion.java + * @compile/fail/ref=AnnotationVersion7.out -XDrawDiagnostics -Xlint:-options -source 1.7 AnnotationVersion.java + */ +class AnnotationVersion { + public void method(@A AnnotationVersion this) { } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out new file mode 100644 index 00000000000..d836ff3532a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out @@ -0,0 +1,2 @@ +AnnotationVersion.java:10:43: compiler.err.type.annotations.not.supported.in.source: 1.6 +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out new file mode 100644 index 00000000000..cb2fca3edce --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out @@ -0,0 +1,2 @@ +AnnotationVersion.java:10:43: compiler.err.type.annotations.not.supported.in.source: 1.7 +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.java new file mode 100644 index 00000000000..a24c323d746 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary A cast cannot consist of only an annotation. + * @author Werner Dietl + * @compile/fail/ref=BadCast.out -XDrawDiagnostics BadCast.java + */ +class BadCast { + static void main() { + Object o = (@A) ""; + } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.out new file mode 100644 index 00000000000..f1b8bf04ca6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/BadCast.out @@ -0,0 +1,2 @@ +BadCast.java:10:19: compiler.err.illegal.start.of.type +1 error \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.java new file mode 100644 index 00000000000..8cd7d6aa155 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.java @@ -0,0 +1,41 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006733 8006775 + * @ignore + * @summary A static outer class cannot be annotated. + * @author Werner Dietl + * @compile/fail/ref=CantAnnotateStaticClass.out -XDrawDiagnostics CantAnnotateStaticClass.java + */ + +import java.util.List; +import java.lang.annotation.*; + +class CantAnnotateStaticClass { + @Target(ElementType.TYPE_USE) + @interface A {} + + static class Outer { + class Inner {} + } + + // 8 errors: + @A Outer.Inner f1; + @A Outer.Inner f1r() { return null; } + void f1p(@A Outer.Inner p) { } + void f1c(Object o) { + Object l = (@A Outer.Inner) o; + } + + List<@A Outer.Inner> f2; + List<@A Outer.Inner> f2r() { return null; } + void f2p(List<@A Outer.Inner> p) { } + void f2c(Object o) { + Object l = (List<@A Outer.Inner>) o; + } + + // OK: + @A Outer g1; + List<@A Outer> g2; + Outer. @A Inner g3; + List g4; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.out new file mode 100644 index 00000000000..2995a4d0e74 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass.out @@ -0,0 +1 @@ +dummy \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.java new file mode 100644 index 00000000000..c414a5f807e --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test incomplete array declaration + * @author Mahmood Ali + * @compile/fail/ref=IncompleteArray.out -XDrawDiagnostics IncompleteArray.java + */ +class IncompleteArray { + int @A [] @A var; +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.out new file mode 100644 index 00000000000..a03a09283ee --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteArray.out @@ -0,0 +1,2 @@ +IncompleteArray.java:9:13: compiler.err.illegal.start.of.type +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.java new file mode 100644 index 00000000000..1bb05a43aec --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test incomplete vararg declaration + * @author Mahmood Ali + * @compile/fail/ref=IncompleteVararg.out -XDrawDiagnostics IncompleteVararg.java + */ +class IncompleteArray { + // the last variable may be vararg + void method(int @A test) { } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.out new file mode 100644 index 00000000000..7cec6c9ee78 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IncompleteVararg.out @@ -0,0 +1,2 @@ +IncompleteVararg.java:10:19: compiler.err.illegal.start.of.type +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.java new file mode 100644 index 00000000000..7098b93ee81 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test indexing of an array + * @author Mahmood Ali + * @compile/fail/ref=IndexArray.out -XDrawDiagnostics IndexArray.java + */ +class IndexArray { + int[] var; + int a = var @A [1]; +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.out new file mode 100644 index 00000000000..762f38b15a8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/IndexArray.out @@ -0,0 +1,2 @@ +IndexArray.java:10:15: compiler.err.illegal.start.of.expr +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.java new file mode 100644 index 00000000000..fdb31832ae5 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.java @@ -0,0 +1,69 @@ +import java.lang.annotation.*; +import java.util.List; + +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test that compiler doesn't warn about annotated redundant casts + * @author Mahmood Ali + * @author Werner Dietl + * @compile/ref=LintCast.out -Xlint:cast -XDrawDiagnostics LintCast.java + */ +class LintCast { + void unparameterized() { + String s = "m"; + String s1 = (String)s; + String s2 = (@A String)s; + } + + void parameterized() { + List l = null; + List l1 = (List)l; + List l2 = (List<@A String>)l; + } + + void array() { + int @A [] a = null; + int[] a1 = (int[])a; + int[] a2 = (int @A [])a; + } + + void sameAnnotations() { + @A String annotated = null; + String unannotated = null; + + // compiler ignore annotated casts even if redundant + @A String anno1 = (@A String)annotated; + + // warn if redundant without an annotation + String anno2 = (String)annotated; + String unanno2 = (String)unannotated; + } + + void more() { + Object @A [] a = null; + Object[] a1 = (Object[])a; + Object[] a2 = (Object @A [])a; + + @A List l3 = null; + List l4 = (List)l3; + List l5 = (@A List)l3; + + List<@A String> l6 = null; + List l7 = (List)l6; + List l8 = (List<@A String>)l6; + + @A Object o = null; + Object o1 = (Object)o; + Object o2 = (@A Object)o; + + Outer. @A Inner oi = null; + Outer.Inner oi1 = (Outer.Inner)oi; + Outer.Inner oi2 = (Outer. @A Inner)oi; + } + + class Outer { class Inner {} } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.out new file mode 100644 index 00000000000..212423e8895 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LintCast.out @@ -0,0 +1,11 @@ +LintCast.java:15:21: compiler.warn.redundant.cast: java.lang.String +LintCast.java:21:27: compiler.warn.redundant.cast: java.util.List +LintCast.java:27:20: compiler.warn.redundant.cast: (@A :: int[]) +LintCast.java:39:24: compiler.warn.redundant.cast: java.lang.String +LintCast.java:40:26: compiler.warn.redundant.cast: java.lang.String +LintCast.java:45:23: compiler.warn.redundant.cast: (@A :: java.lang.Object[]) +LintCast.java:49:27: compiler.warn.redundant.cast: java.util.List +LintCast.java:53:27: compiler.warn.redundant.cast: java.util.List +LintCast.java:57:21: compiler.warn.redundant.cast: java.lang.Object +LintCast.java:61:27: compiler.warn.redundant.cast: LintCast.Outer.Inner +10 warnings \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.java new file mode 100644 index 00000000000..4ed4e87aec1 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6843077 8006775 + * @summary test old array syntax + * @author Mahmood Ali + * @compile/fail -XDrawDiagnostics OldArray.java + */ +class OldArray { + String [@A] s() { return null; } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.java new file mode 100644 index 00000000000..aab3c55832c --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.java @@ -0,0 +1,17 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check that A is accessible in the class type parameters + * @author Mahmood Ali + * @compile/fail/ref=Scopes.out -XDrawDiagnostics Scopes.java + */ +class Scopes { + // UniqueInner is not visible in the type parameters. + // One has to use Scopes.UniqueInner. + // Annotations with the default @Target are not allowed there, + // so we also get the second error about the invalid location. + // Adding the target here doesn't matter, as we don't resolve + // the annotation type. + // @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface UniqueInner { }; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.out new file mode 100644 index 00000000000..cf7eeceb9d8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/Scopes.out @@ -0,0 +1,3 @@ +Scopes.java:8:25: compiler.err.cant.resolve: kindname.class, UniqueInner, , +Scopes.java:8:24: compiler.err.annotation.type.not.applicable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.java new file mode 100644 index 00000000000..f75583f9688 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary static field access isn't a valid location + * @author Mahmood Ali + * @compile/fail/ref=StaticFields.out -XDrawDiagnostics StaticFields.java + */ +class C { + int f; + int a = @A C.f; +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.out new file mode 100644 index 00000000000..3364c661fdb --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticFields.out @@ -0,0 +1,2 @@ +StaticFields.java:10:17: compiler.err.illegal.start.of.expr +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.java new file mode 100644 index 00000000000..cb386d1abab --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary static methods don't have receivers + * @author Mahmood Ali + * @compile/fail/ref=StaticMethods.out -XDrawDiagnostics StaticMethods.java + */ +class StaticMethods { + static void main(@A StaticMethods this) { } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.out new file mode 100644 index 00000000000..d75a02bffe3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/StaticMethods.out @@ -0,0 +1,2 @@ +StaticMethods.java:9:37: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeAndField.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeAndField.java new file mode 100644 index 00000000000..4f600f44abc --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeAndField.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006703 8006775 + * @summary Ensure that TYPE_USE and FIELD work together. + * @author Werner Dietl + * @compile TypeAndField.java + */ +import java.lang.annotation.*; + +class TypeAndField { + @TA Integer i; + @TA int j; +} + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE_USE, ElementType.FIELD}) +@interface TA { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java new file mode 100644 index 00000000000..38a0395ffab --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6843077 8006775 + * @summary test type annotation on void generic methods + * @author Mahmood Ali + * @compile/fail VoidGenericMethod.java + */ +class VoidGenericMethod { + public @A void method() { } +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..cc0b2d96db9 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void test() { + String @A(value = 2, value = 1) [] s; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..566321c05db --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:11:26: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..da0438eda17 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnnotation { + void test() { + String @A @A [] s; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..3c5f6ea1c68 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:11:12: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:11:15: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.java new file mode 100644 index 00000000000..da44d219383 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + void test() { + String @A [] s; + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.out new file mode 100644 index 00000000000..868ab979837 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:11:12: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.java new file mode 100644 index 00000000000..4f099e03156 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void test() { + String @A [] s; + } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.out new file mode 100644 index 00000000000..74a7ef7340b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/arrays/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:12: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..2230767d300 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void method() { + class Inner<@A(value = 2, value = 1) K> {} + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..12248c81a87 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:11:31: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..3438dd2a9fc --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno { + void innermethod() { + class Inner<@A @A K> { } + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..7eb43efa3ed --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:11:17: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:11:20: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.java new file mode 100644 index 00000000000..46d65a8daef --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ +class InvalidLocation { + void innermethod() { + class Inner<@A K> {} + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.out new file mode 100644 index 00000000000..b74ad54ba94 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:10:17: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.java new file mode 100644 index 00000000000..5a5c8b69587 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void innermethod() { + class Inner<@A K> { } + } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.out new file mode 100644 index 00000000000..637ff4acc0a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/innertypeparams/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:17: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..f3f36165b64 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void test() { + String[] a = new String @A(value = 2, value = 1) [5] ; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..cb7b69d86f9 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:11:43: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..be8f479fedf --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnnotation { + void test() { + String[] a = new String @A @A [5] ; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..537e6156ef3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:11:29: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:11:32: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.java new file mode 100644 index 00000000000..a43e2e7b070 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + void test() { + String[] s = new String @A [5] ; + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.out new file mode 100644 index 00000000000..1d98d174319 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:11:29: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.java new file mode 100644 index 00000000000..15cf6e91496 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void test() { + String[] a = new String @A [5]; + } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.out new file mode 100644 index 00000000000..6865348250b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/newarray/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:29: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.java new file mode 100644 index 00000000000..7e4581851e5 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.java @@ -0,0 +1,99 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8006775 + * @summary Ensure unresolved upper bound annotation is handled correctly + * @author Werner Dietl + * @compile/fail/ref=BrokenAnnotation.out -XDrawDiagnostics BrokenAnnotation.java + */ + +// No import, making the annotation @A invalid. +// import java.lang.annotation.*; + +// Works: @Broke.A class... +// Works: class Broke<@Broke.A T> { +// Used to fail: +class BrokenAnnotation { + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) + @interface A { } +} + +// If the Annotation is e.g. on the top-level class, we +// get something like this: +// +// Broke.java:6: cannot find symbol +// symbol : class Target +// location: class Broke +// @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +// ^ +// 1 error +// +// When the annotation is in the upper bound, one used to get +// the following stack trace: +// +// An exception has occurred in the compiler (1.7.0-jsr308-1.2.7). Please report this bug so we can fix it. For instructions, see http://types.cs.washington.edu/checker-framework/current/README-jsr308.html#reporting-bugs . Thank you. +// java.lang.NullPointerException +// at com.sun.tools.javac.code.Type.isCompound(Type.java:346) +// at com.sun.tools.javac.code.Types.getBounds(Types.java:1940) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visitTypeVar(RichDiagnosticFormatter.java:534) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visitTypeVar(RichDiagnosticFormatter.java:1) +// at com.sun.tools.javac.code.Type$TypeVar.accept(Type.java:1049) +// at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3809) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visit(RichDiagnosticFormatter.java:450) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visitClassType(RichDiagnosticFormatter.java:518) +// at com.sun.tools.javac.util.RichDiagnosticFormatter$1.visitClassType(RichDiagnosticFormatter.java:1) +// at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:596) +// at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3809) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessType(RichDiagnosticFormatter.java:442) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessArgument(RichDiagnosticFormatter.java:172) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessDiagnostic(RichDiagnosticFormatter.java:155) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessArgument(RichDiagnosticFormatter.java:178) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.preprocessDiagnostic(RichDiagnosticFormatter.java:155) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.format(RichDiagnosticFormatter.java:111) +// at com.sun.tools.javac.util.RichDiagnosticFormatter.format(RichDiagnosticFormatter.java:1) +// at com.sun.tools.javac.util.Log.writeDiagnostic(Log.java:514) +// at com.sun.tools.javac.util.Log.report(Log.java:496) +// at com.sun.tools.javac.comp.Resolve.logResolveError(Resolve.java:2160) +// at com.sun.tools.javac.comp.Resolve.access(Resolve.java:1553) +// at com.sun.tools.javac.comp.Resolve.access(Resolve.java:1580) +// at com.sun.tools.javac.comp.Resolve.access(Resolve.java:1592) +// at com.sun.tools.javac.comp.Resolve.resolveIdent(Resolve.java:1653) +// at com.sun.tools.javac.comp.Attr.visitIdent(Attr.java:2191) +// at com.sun.tools.javac.tree.JCTree$JCIdent.accept(JCTree.java:1873) +// at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:467) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:503) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:496) +// at com.sun.tools.javac.comp.Attr.attribAnnotationTypes(Attr.java:605) +// at com.sun.tools.javac.comp.MemberEnter.complete(MemberEnter.java:944) +// at com.sun.tools.javac.code.Symbol.complete(Symbol.java:432) +// at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:832) +// at com.sun.tools.javac.code.Symbol$ClassSymbol.flags(Symbol.java:775) +// at com.sun.tools.javac.comp.Resolve.isAccessible(Resolve.java:350) +// at com.sun.tools.javac.comp.Resolve.isAccessible(Resolve.java:346) +// at com.sun.tools.javac.comp.Resolve.findMemberType(Resolve.java:1346) +// at com.sun.tools.javac.comp.Resolve.findIdentInType(Resolve.java:1512) +// at com.sun.tools.javac.comp.Attr.selectSym(Attr.java:2434) +// at com.sun.tools.javac.comp.Attr.visitSelect(Attr.java:2312) +// at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:1805) +// at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:467) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:503) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:496) +// at com.sun.tools.javac.comp.Attr.attribAnnotationTypes(Attr.java:605) +// at com.sun.tools.javac.comp.Attr.visitAnnotatedType(Attr.java:3016) +// at com.sun.tools.javac.tree.JCTree$JCAnnotatedType.accept(JCTree.java:2253) +// at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:467) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:503) +// at com.sun.tools.javac.comp.Attr.attribType(Attr.java:496) +// at com.sun.tools.javac.comp.Attr.attribTypeVariables(Attr.java:569) +// at com.sun.tools.javac.comp.MemberEnter.complete(MemberEnter.java:955) +// at com.sun.tools.javac.code.Symbol.complete(Symbol.java:432) +// at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:832) +// at com.sun.tools.javac.comp.Enter.complete(Enter.java:500) +// at com.sun.tools.javac.comp.Enter.main(Enter.java:478) +// at com.sun.tools.javac.main.JavaCompiler.enterTrees(JavaCompiler.java:950) +// at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:841) +// at com.sun.tools.javac.main.Main.compile(Main.java:441) +// at com.sun.tools.javac.main.Main.compile(Main.java:358) +// at com.sun.tools.javac.main.Main.compile(Main.java:347) +// at com.sun.tools.javac.main.Main.compile(Main.java:338) +// at com.sun.tools.javac.Main.compile(Main.java:76) +// at com.sun.tools.javac.Main.main(Main.java:61) diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.out new file mode 100644 index 00000000000..caeb4bb158d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/BrokenAnnotation.out @@ -0,0 +1,3 @@ +BrokenAnnotation.java:16:6: compiler.err.cant.resolve.location: kindname.class, Target, , , (compiler.misc.location: kindname.class, BrokenAnnotation, null) +BrokenAnnotation.java:15:34: compiler.err.annotation.type.not.applicable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..ae1a043495f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..5badf2cc240 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:9:56: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..0e64a844f57 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno { +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..09b7843aaf3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:9:35: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:9:38: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.java new file mode 100644 index 00000000000..374a143d26a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.out new file mode 100644 index 00000000000..d474f174346 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:9:33: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.java new file mode 100644 index 00000000000..58cb921c925 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +import java.lang.annotation.*; + +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { +} + +@Target(ElementType.TYPE_USE) +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.out new file mode 100644 index 00000000000..89f3ef0de98 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/parambounds/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:40: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..aa0dd5c1eb6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values in receiver + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void test(@A(value = 2, value = 1) DuplicateAnnotationValue this) { } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..73cff02fa91 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:10:27: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..1ba2846c42d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations in receiver + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnnotation { + void test(@A @A DuplicateTypeAnnotation this) { } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..a2f6dba28c3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:10:13: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:10:16: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.java new file mode 100644 index 00000000000..a0f03434387 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + void test(@A InvalidLocation this) { + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.out new file mode 100644 index 00000000000..96a01cec454 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:10:13: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.java new file mode 100644 index 00000000000..4043ed6bc50 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void test(@A MissingAnnotationValue this) { } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.out new file mode 100644 index 00000000000..c83391029bf --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:9:13: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/Nesting.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/Nesting.java new file mode 100644 index 00000000000..6b5d7fc3a9f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/Nesting.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8006775 + * @summary Ensure that nested classes/methods work + * @author Werner Dietl + * @compile Nesting.java + */ +@interface A { } + +class Nesting { + void top(@A Nesting this) {} + + class B { + void inB(@A B this) {} + } + + void meth(@A Nesting this) { + class C { + void inMethod(@A C this) {} + } + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.java new file mode 100644 index 00000000000..35ee8432812 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8006775 + * @summary the receiver parameter and static methods/classes + * @author Werner Dietl + * @compile/fail/ref=StaticThings.out -XDrawDiagnostics StaticThings.java + */ +class Test { + // bad + static void test1(Test this) {} + + // bad + static Object test2(Test this) { return null; } + + class Nested1 { + // good + void test3a(Nested1 this) {} + // good + void test3b(Test.Nested1 this) {} + // No static methods + // static void test3c(Nested1 this) {} + } + static class Nested2 { + // good + void test4a(Nested2 this) {} + // good + void test4b(Test.Nested2 this) {} + // bad + static void test4c(Nested2 this) {} + // bad + static void test4d(Test.Nested2 this) {} + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.out new file mode 100644 index 00000000000..fc50011c1b8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/StaticThings.out @@ -0,0 +1,5 @@ +StaticThings.java:52:32: compiler.err.annotation.type.not.applicable +StaticThings.java:54:37: compiler.err.annotation.type.not.applicable +StaticThings.java:33:26: compiler.err.annotation.type.not.applicable +StaticThings.java:36:28: compiler.err.annotation.type.not.applicable +4 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.java new file mode 100644 index 00000000000..63277109f30 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8006775 + * @summary the receiver parameter has the type of the surrounding class + * @author Werner Dietl + * @compile/fail/ref=WrongType.out -XDrawDiagnostics WrongType.java + */ + +@interface A {} + +class WrongType { + Object f; + + void good1(@A WrongType this) {} + + void good2(@A WrongType this) { + this.f = null; + Object o = this.f; + } + + void bad1(@A Object this) {} + + void bad2(@A Object this) { + this.f = null; + Object o = this.f; + } + + void wow(@A XYZ this) { + this.f = null; + } + + class Inner { + void good1(@A Inner this) {} + void good2(@A WrongType.Inner this) {} + + void outerOnly(@A WrongType this) {} + void wrongInner(@A Object this) {} + void badOuter(@A Outer.Inner this) {} + void badInner(@A WrongType.XY this) {} + } + + class Generics { + void m(Generics this) {} + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.out new file mode 100644 index 00000000000..804425aaf76 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/receiver/WrongType.out @@ -0,0 +1,9 @@ +WrongType.java:51:15: compiler.err.cant.resolve.location: kindname.class, XYZ, , , (compiler.misc.location: kindname.class, WrongType, null) +WrongType.java:61:27: compiler.err.doesnt.exist: Outer +WrongType.java:62:31: compiler.err.cant.resolve.location: kindname.class, XY, , , (compiler.misc.location: kindname.class, WrongType, null) +WrongType.java:44:23: compiler.err.incorrect.receiver.type +WrongType.java:46:23: compiler.err.incorrect.receiver.type +WrongType.java:59:33: compiler.err.incorrect.receiver.type +WrongType.java:60:31: compiler.err.incorrect.receiver.type +WrongType.java:66:28: compiler.err.incorrect.receiver.type +8 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..5f399fa276f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for Duplicate annotation value + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + void test() { + new @A String(); + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..dd7e50bbade --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:11:9: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..014490f6104 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnnotation { + void test() { + new @A @A String(); + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..04b67141421 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:11:9: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:11:12: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.java new file mode 100644 index 00000000000..c3622976c75 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + void test() { + new @A String(); + } +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.out new file mode 100644 index 00000000000..ad9861c2f6f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:11:9: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.java new file mode 100644 index 00000000000..5a6bb4299b8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + void test() { + new @A String(); + } +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.out new file mode 100644 index 00000000000..f83f6dfa58a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/rest/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:10:9: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..a1f432e5563 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + DuplicateAnnotationValue<@A(value = 2, value = 1) String> l; +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..c8e21def939 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:10:42: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..c25afb5c412 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno { + DuplicateTypeAnno<@A @A String> l; +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..3b6802d9038 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:10:21: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:10:24: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.java new file mode 100644 index 00000000000..4b12e79df24 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + InvalidLocation<@A String> l; +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.out new file mode 100644 index 00000000000..30841b78f0f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:10:19: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.java new file mode 100644 index 00000000000..a6e00304fa1 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + MissingAnnotationValue<@A String> l; +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.out new file mode 100644 index 00000000000..749442f45b6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeArgs/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:9:26: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..22ab06ef225 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue<@A(value = 2, value = 1) K> { +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..b3485b2332b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:9:46: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..20883a0ba85 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno<@A @A K> { +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..6fd3ba6e32b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:9:25: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:9:28: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.java new file mode 100644 index 00000000000..094a76ccab1 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation<@A K> { +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.out new file mode 100644 index 00000000000..87d42a278c4 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:9:23: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.java new file mode 100644 index 00000000000..39f8bee930f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.java @@ -0,0 +1,11 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue<@A K> { +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.out new file mode 100644 index 00000000000..acac021869b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/typeparams/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:8:30: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java new file mode 100644 index 00000000000..7355719f607 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 6919944 8006775 + * @summary check for duplicate annotation values for type parameter + * @author Mahmood Ali + * @compile/fail/ref=DuplicateAnnotationValue.out -XDrawDiagnostics DuplicateAnnotationValue.java + */ +import java.lang.annotation.*; +class DuplicateAnnotationValue { + DuplicateAnnotationValue<@A(value = 2, value = 1) ?> l; +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out new file mode 100644 index 00000000000..c8e21def939 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateAnnotationValue.out @@ -0,0 +1,2 @@ +DuplicateAnnotationValue.java:10:42: compiler.err.duplicate.annotation.member.value: value, A +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.java new file mode 100644 index 00000000000..17ac7a98cbe --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for duplicate annotations + * @author Mahmood Ali + * @compile/fail/ref=DuplicateTypeAnnotation.out -XDrawDiagnostics DuplicateTypeAnnotation.java + */ +import java.lang.annotation.*; +class DuplicateTypeAnno { + DuplicateTypeAnno<@A @A ?> l; +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.out new file mode 100644 index 00000000000..3b6802d9038 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/DuplicateTypeAnnotation.out @@ -0,0 +1,3 @@ +DuplicateTypeAnnotation.java:10:21: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +DuplicateTypeAnnotation.java:10:24: compiler.err.duplicate.annotation.missing.container: A, java.lang.annotation.Repeatable +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.java new file mode 100644 index 00000000000..eee6ed28b73 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for invalid annotatins given the target + * @author Mahmood Ali + * @compile/fail/ref=InvalidLocation.out -XDrawDiagnostics InvalidLocation.java + */ + +class InvalidLocation { + InvalidLocation<@A ?> l; +} + +@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.out new file mode 100644 index 00000000000..30841b78f0f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/InvalidLocation.out @@ -0,0 +1,2 @@ +InvalidLocation.java:10:19: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.java new file mode 100644 index 00000000000..c111c895c7d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary check for missing annotation value + * @author Mahmood Ali + * @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java + */ +class MissingAnnotationValue { + MissingAnnotationValue<@A ?> l; +} + +@interface A { int field(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.out new file mode 100644 index 00000000000..749442f45b6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/common/wildcards/MissingAnnotationValue.out @@ -0,0 +1,2 @@ +MissingAnnotationValue.java:9:26: compiler.err.annotation.missing.default.value: A, field +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.java new file mode 100644 index 00000000000..bbba6345611 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.java @@ -0,0 +1,37 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test invalid location of TypeUse + * @author Mahmood Ali + * @compile/fail/ref=Constructor.out -XDrawDiagnostics Constructor.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class Constructor { + // Constructor result type use annotation + @A Constructor() { } + + // Not type parameter annotation + @B Constructor(int x) { } + + // TODO add err: no "this" receiver parameter for constructors + // Constructor(@A Constructor this, Object o) { } + + // TODO: support Outer.this. +} + +class Constructor2 { + class Inner { + // OK + @A Inner() { } + } +} + +@Target(ElementType.TYPE_USE) +@interface A { } + +@Target(ElementType.TYPE_PARAMETER) +@interface B { } + diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.out new file mode 100644 index 00000000000..05689245d5f --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/Constructor.out @@ -0,0 +1,2 @@ +Constructor.java:17:3: compiler.err.annotation.type.not.applicable +1 error \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java new file mode 100644 index 00000000000..6363da0a301 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 Class literals are not type uses and cannot be annotated + * @author Werner Dietl + * @compile/fail/ref=DotClass.out -XDrawDiagnostics DotClass.java + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.TYPE_PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; + +@Target({TYPE_USE, TYPE_PARAMETER, TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@interface A {} + +@interface B { int value(); } + +class T0x1E { + void m0x1E() { + Class c = @A Object.class; + } + + Class c = @A String.class; + + Class as = @A String.class; +} + +class ClassLiterals { + public static void main(String[] args) { + if (String.class != @A String.class) throw new Error(); + if (@A int.class != int.class) throw new Error(); + if (@A int.class != Integer.TYPE) throw new Error(); + if (@A int @B(0) [].class != int[].class) throw new Error(); + + if (String[].class != @A String[].class) throw new Error(); + if (String[].class != String @A [].class) throw new Error(); + if (@A int[].class != int[].class) throw new Error(); + if (@A int @B(0) [].class != int[].class) throw new Error(); + } + + Object classLit1 = @A String @C [] @B(0) [].class; + Object classLit2 = @A String @C [] [].class; + Object classLit3 = @A String [] @B(0) [].class; + Object classLit4 = String [] @B(0) [].class; + Object classLit5 = String @C [] [].class; + Object classLit6 = String [] [].class; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.out new file mode 100644 index 00000000000..c40f3d7cd74 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.out @@ -0,0 +1,17 @@ +DotClass.java:47:42: compiler.err.no.annotations.on.dot.class +DotClass.java:50:33: compiler.err.no.annotations.on.dot.class +DotClass.java:52:52: compiler.err.no.annotations.on.dot.class +DotClass.java:57:44: compiler.err.no.annotations.on.dot.class +DotClass.java:58:26: compiler.err.no.annotations.on.dot.class +DotClass.java:59:26: compiler.err.no.annotations.on.dot.class +DotClass.java:60:35: compiler.err.no.annotations.on.dot.class +DotClass.java:62:48: compiler.err.no.annotations.on.dot.class +DotClass.java:63:49: compiler.err.no.annotations.on.dot.class +DotClass.java:64:28: compiler.err.no.annotations.on.dot.class +DotClass.java:65:35: compiler.err.no.annotations.on.dot.class +DotClass.java:68:54: compiler.err.no.annotations.on.dot.class +DotClass.java:69:54: compiler.err.no.annotations.on.dot.class +DotClass.java:70:54: compiler.err.no.annotations.on.dot.class +DotClass.java:71:54: compiler.err.no.annotations.on.dot.class +DotClass.java:72:54: compiler.err.no.annotations.on.dot.class +16 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.java new file mode 100644 index 00000000000..c414a5f807e --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test incomplete array declaration + * @author Mahmood Ali + * @compile/fail/ref=IncompleteArray.out -XDrawDiagnostics IncompleteArray.java + */ +class IncompleteArray { + int @A [] @A var; +} + +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.out new file mode 100644 index 00000000000..a03a09283ee --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/IncompleteArray.out @@ -0,0 +1,2 @@ +IncompleteArray.java:9:13: compiler.err.illegal.start.of.type +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.java new file mode 100644 index 00000000000..49ba85f344d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.java @@ -0,0 +1,25 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test invalid location of TypeUse and TypeParameter + * @author Mahmood Ali + * @compile/fail/ref=NotTypeParameter.out -XDrawDiagnostics NotTypeParameter.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class VoidMethod<@A K> { + @A void test() { } +} + +@Target(ElementType.TYPE_USE) +@interface A { } + +class TypeVariable<@B T> { + @B T test1() { return null; } + void test2(@B T p) {} +} + +@Target(ElementType.TYPE_PARAMETER) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.out new file mode 100644 index 00000000000..40e4ebc7068 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeParameter.out @@ -0,0 +1,4 @@ +NotTypeParameter.java:13:3: compiler.err.annotation.type.not.applicable +NotTypeParameter.java:20:3: compiler.err.annotation.type.not.applicable +NotTypeParameter.java:21:14: compiler.err.annotation.type.not.applicable +3 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.java new file mode 100644 index 00000000000..6c8bfeee3b6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.java @@ -0,0 +1,17 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test invalid location of TypeUse + * @author Mahmood Ali + * @compile/fail/ref=NotTypeUse.out -XDrawDiagnostics NotTypeUse.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class VoidMethod { + @A void test() { } +} + +@Target(ElementType.TYPE) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.out new file mode 100644 index 00000000000..9728d3589ec --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/NotTypeUse.out @@ -0,0 +1,2 @@ +NotTypeUse.java:13:3: compiler.err.annotation.type.not.applicable +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.java new file mode 100644 index 00000000000..a82768ce76b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.java @@ -0,0 +1,33 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test invalid location of TypeUse and TypeParameter + * @author Mahmood Ali + * @compile/fail/ref=VoidMethod.out -XDrawDiagnostics VoidMethod.java + */ + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +class VoidMethod { + // Invalid + @A void test1() { } + // The following is legal: + @B void test2() { } + // Invalid + @C void test3() { } + // The following is legal: + @D void test4() { } +} + +@Target(ElementType.TYPE_USE) +@interface A { } + +@Target({ElementType.TYPE_USE, ElementType.METHOD}) +@interface B { } + +@Target(ElementType.TYPE_PARAMETER) +@interface C { } + +@Target({ElementType.TYPE_PARAMETER, ElementType.METHOD}) +@interface D { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.out new file mode 100644 index 00000000000..7cbba4aa163 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/VoidMethod.out @@ -0,0 +1,3 @@ +VoidMethod.java:14:3: compiler.err.annotation.type.not.applicable +VoidMethod.java:18:3: compiler.err.annotation.type.not.applicable +2 errors diff --git a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/BasicTest.java similarity index 73% rename from langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.java rename to langtools/test/tools/javac/annotations/typeAnnotations/newlocations/BasicTest.java index a5de45959cb..8c7fb83a3f1 100644 --- a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/BasicTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,22 +24,25 @@ /* * @test - * @bug 6843077 + * @bug 6843077 8006775 * @summary random tests for new locations * @author Matt Papi - * @compile/fail/ref=BasicTest.out -XDrawDiagnostics BasicTest.java + * @compile BasicTest.java */ +import java.lang.annotation.*; import java.util.*; import java.io.*; +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface A {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface B {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface C {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface D {} -//308: Test inverted to verify that type annotations can not be parsed yet. - /** * Tests basic JSR 308 parser functionality. We don't really care about what * the parse tree looks like, just that these annotations can be parsed. @@ -48,8 +51,7 @@ class BasicTest extends @B LinkedList implements @C List void test() { - // Handle annotated class literals/cast types - Class c = @A String.class; + // Handle annotated cast types Object o = (@A Object) "foo"; // Handle annotated "new" expressions (except arrays; see ArrayTest) @@ -57,21 +59,23 @@ class BasicTest extends @B LinkedList implements @C List boolean b = o instanceof @A Object; - @A Map<@B List<@C String>, @D String> map = new @A HashMap<@B List<@C String>, @D String>(); - Class c2 = @A String.class; + Class c2 = null; } // Handle receiver annotations // Handle annotations on a qualified identifier list - void test2() @C @D throws @A IllegalArgumentException, @B IOException { + void test2(@C @D BasicTest this) throws @A IllegalArgumentException, @B IOException { } // Handle annotations on a varargs element type - void test3(Object @A... objs) { + void test3(@B Object @A... objs) { } - } + void test4(@B Class<@C ?> @A ... clz) { } + + + // TODO: add more tests... nested classes, etc. } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassExtends.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassExtends.java new file mode 100644 index 00000000000..24df0774fa4 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassExtends.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: class extends/implements + * @author Mahmood Ali + * @compile ClassExtends.java + */ +abstract class MyClass extends @A ParameterizedClass<@B String> + implements @B CharSequence, @A ParameterizedInterface<@B String> { } + +interface MyInterface extends @A ParameterizedInterface<@A String>, + @B CharSequence { } + +class ParameterizedClass {} +interface ParameterizedInterface {} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassParameters.java new file mode 100644 index 00000000000..9b2fbbe8045 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ClassParameters.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: class type parameter bounds + * @author Mahmood Ali + * @compile ClassParameters.java + */ +class Unannotated { } + +class ExtendsBound { } +class ExtendsGeneric> { } +class TwoBounds { } + +class Complex1 { } +class Complex2 { } +class ComplexBoth { } + +class Outer { + void inner() { + class Unannotated { } + + class ExtendsBound { } + class ExtendsGeneric> { } + class TwoBounds { } + + class Complex1 { } + class Complex2 { } + class ComplexBoth { } + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ConstructorTypeArgs.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ConstructorTypeArgs.java new file mode 100644 index 00000000000..6db9804fdee --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ConstructorTypeArgs.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: constructor type args + * @author Mahmood Ali + * @compile ConstructorTypeArgs.java + */ + +class ConstructorTypeArgs { + void oneArg() { + new @A MyList<@A String>(); + new MyList<@A MyList<@B(0) String>>(); + } + + void twoArg() { + new MyMap(); + new MyMap<@A String, @B(0) MyList<@A String>>(); + } + + void withArraysIn() { + new MyList(); + new MyList<@A String @B(0) [] @A []>(); + + new MyMap<@A String[], @B(0) MyList<@A String> @A []>(); + } +} + +class MyList { } +class MyMap { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ExceptionParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ExceptionParameters.java new file mode 100644 index 00000000000..81b327c5c04 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ExceptionParameters.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 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.lang.annotation.*; + +import java.io.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: exception parameters + * @author Werner Dietl + * @compile ExceptionParameters.java + */ + +class ExceptionParameters { + + void exception() { + try { + foobar(); + } catch (@A Exception e) { + e.toString(); + } + } + + void finalException() { + try { + foobar(); + } catch (final @B Exception e) { + e.toString(); + } + } + + void multiException1() { + try { + foobar(); + } catch (@A NullPointerException | @B IndexOutOfBoundsException e) { + e.toString(); + } + } + + void multiException2() { + try { + foobar(); + } catch (java.lang.@A NullPointerException | java.lang.@B IndexOutOfBoundsException e) { + e.toString(); + } + } + + void foobar() {} +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Expressions.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Expressions.java new file mode 100644 index 00000000000..bd4acc9c895 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Expressions.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: expressions + * @author Mahmood Ali + * @compile Expressions.java + */ +class Expressions { + void instanceOf() { + Object o = null; + boolean a = o instanceof @A String; + boolean b = o instanceof @B(0) String; + } + + void instanceOfArray() { + Object o = null; + boolean a1 = o instanceof @A String []; + boolean a2 = o instanceof @B(0) String []; + + boolean b1 = o instanceof String @A []; + boolean b2 = o instanceof String @B(0) []; + } + + void objectCreation() { + new @A String(); + new @B(0) String(); + } + + void objectCreationArray() { + Object a1 = new @A String [] [] { }; + Object a2 = new @A String [1] []; + Object a3 = new @A String [1] [2]; + + Object b1 = new @A String @B(0) [] [] { }; + Object b2 = new @A String @B(0) [1] []; + Object b3 = new @A String @B(0) [1] [2]; + + Object c1 = new @A String [] @B(0) [] { }; + Object c2 = new @A String [1] @B(0) []; + Object c3 = new @A String [1] @B(0) [2]; + + Object d1 = new @A String @B(0) [] @B(0) [] { }; + Object d2 = new @A String @B(0) [1] @B(0) []; + Object d3 = new @A String @B(0) [1] @B(0) [2]; + + Object rand = new @A String @B(value = 0) [1] @B(value = 0) [2]; + + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Fields.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Fields.java new file mode 100644 index 00000000000..04fb39f021e --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Fields.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: field type array/generics + * @author Mahmood Ali + * @compile Fields.java + */ + +class DefaultScope { + Parameterized unannotated; + Parameterized<@A String, String> firstTypeArg; + Parameterized secondTypeArg; + Parameterized<@A String, @B String> bothTypeArgs; + + Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized; + + @A String [] array1; + @A String @B [] array1Deep; + @A String [] [] array2; + @A String @A [] @B [] array2Deep; + String @A [] [] array2First; + String [] @B [] array2Second; + + // Old-style array syntax + String array2FirstOld @A []; + String array2SecondOld [] @B []; +} + +class ModifiedScoped { + public final Parameterized unannotated = null; + public final Parameterized<@A String, String> firstTypeArg = null; + public final Parameterized secondTypeArg = null; + public final Parameterized<@A String, @B String> bothTypeArgs = null; + + public final Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized = null; + + public final @A String [] array1 = null; + public final @A String @B [] array1Deep = null; + public final @A String [] [] array2 = null; + public final @A String @A [] @B [] array2Deep = null; + public final String @A [] [] array2First = null; + public final String [] @B [] array2Second = null; +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/LocalVariables.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/LocalVariables.java new file mode 100644 index 00000000000..9f057f5807a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/LocalVariables.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: local variables array/generics + * @author Mahmood Ali + * @compile LocalVariables.java + */ + +class DefaultScope { + void parameterized() { + Parameterized unannotated; + Parameterized<@A String, String> firstTypeArg; + Parameterized secondTypeArg; + Parameterized<@A String, @B String> bothTypeArgs; + + Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized; + } + + void arrays() { + @A String [] array1; + @A String @B [] array1Deep; + @A String [] [] array2; + @A String @A [] @B [] array2Deep; + String @A [] [] array2First; + String [] @B [] array2Second; + } +} + +class ModifiedVars { + void parameterized() { + final Parameterized unannotated = null; + final Parameterized<@A String, String> firstTypeArg = null; + final Parameterized secondTypeArg = null; + final Parameterized<@A String, @B String> bothTypeArgs = null; + + final Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized = null; + } + + void arrays() { + final @A String [] array1 = null; + final @A String @B [] array1Deep = null; + final @A String [] [] array2 = null; + final @A String @A [] @B [] array2Deep = null; + final String @A [] [] array2First = null; + final String [] @B [] array2Second = null; + } +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodReturnType.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodReturnType.java new file mode 100644 index 00000000000..1a3b4905155 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodReturnType.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: method return type array/generics + * @author Mahmood Ali + * @compile MethodReturnType.java + */ + +class DefaultScope { + Parameterized unannotated() { return null; } + Parameterized<@A String, String> firstTypeArg() { return null; } + Parameterized secondTypeArg() { return null; } + Parameterized<@A String, @B String> bothTypeArgs() { return null; } + + Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized() { return null; } + + public @A String method() { return null; } + + @A String [] array1() { return null; } + @A String @B [] array1Deep() { return null; } + @A String [] [] array2() { return null; } + @A String @A [] @B [] array2Deep() { return null; } + String @A [] [] array2First() { return null; } + String [] @B [] array2Second() { return null; } + + // Old-style array syntax + String array2FirstOld() @A [] { return null; } + String array2SecondOld() [] @B [] { return null; } +} + +class ModifiedScoped { + public final Parameterized unannotated() { return null; } + public final Parameterized<@A String, String> firstTypeArg() { return null; } + public final Parameterized secondTypeArg() { return null; } + public final Parameterized<@A String, @B String> bothTypeArgs() { return null; } + + public final Parameterized<@A Parameterized<@A String, @B String>, @B String> + nestedParameterized() { return null; } + + public final @A String [] array1() { return null; } + public final @A String @B [] array1Deep() { return null; } + public final @A String [] [] array2() { return null; } + public final @A String @A [] @B [] array2Deep() { return null; } + public final String @A [] [] array2First() { return null; } + public final String [] @B [] array2Second() { return null; } +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeArgs.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeArgs.java new file mode 100644 index 00000000000..1da62766208 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeArgs.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: method type args + * @author Mahmood Ali + * @compile MethodTypeArgs.java + */ + +class MethodTypeArgs { + void oneArg() { + this.<@A String>newList(); + this.<@A MyList<@B(0) String>>newList(); + + MethodTypeArgs.<@A String>newList(); + MethodTypeArgs.<@A MyList<@B(0) String>>newList(); + } + + void twoArg() { + this.newMap(); + this.<@A String, @B(0) MyList<@A String>>newMap(); + + MethodTypeArgs.newMap(); + MethodTypeArgs.<@A String, @B(0) MyList<@A String>>newMap(); + } + + void withArraysIn() { + this.newList(); + this.<@A String @B(0) [] @A []>newList(); + + this.<@A String[], @B(0) MyList<@A String> @A []>newMap(); + } + + static void newList() { } + static void newMap() { } +} + +class MyList { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { int value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeParameters.java new file mode 100644 index 00000000000..4363af11364 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MethodTypeParameters.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: method type parameter bounds + * @author Mahmood Ali + * @compile MethodTypeParameters.java + */ + +class UnscopedUnmodified { + void methodExtends() {} + > void nestedExtends() {} + > void dual() {} + > void dualOneAnno() {} +} + +class PublicModifiedMethods { + public final void methodExtends() {} + public final > void nestedExtends() {} + public final > void dual() {} + public final > void dualOneAnno() {} +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MultiCatch.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MultiCatch.java new file mode 100644 index 00000000000..1745e61ae6b --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/MultiCatch.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @ignore // syntax not sure yet. + * @bug 8006775 + * @summary new type annotation location: multicatch + * @author Werner Dietl + * @compile MultiCatch.java + */ + +class DefaultScope { + void exception01() { + try { + System.out.println("Hello 1!"); + } catch (@B NullPointerException | @C IllegalArgumentException e) { + e.toString(); + } + } + void exception02() { + try { + System.out.println("Hello 2!"); + } catch @A (@B NullPointerException | @C IllegalArgumentException e) { + e.toString(); + } + } +} + +class ModifiedVars { + /* + void exception() { + try { + arrays(); + } catch (final @A Exception e) { + e.toString(); + } + } + */ +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface C { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface D { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/NestedTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/NestedTypes.java new file mode 100644 index 00000000000..7572b4fefb2 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/NestedTypes.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; +import java.util.Map; + +/* + * @test + * @bug 8006775 + * @summary new type annotation location: nested types + * @author Werner Dietl + * @compile NestedTypes.java + */ +class Outer { + class Inner { + class Inner2 { + // m1a-c all have the same parameter type. + void m1a(@A Inner2 p1a) {} + void m1b(Inner.@A Inner2 p1b) {} + void m1c(Outer.Inner.@A Inner2 p1c) {} + // notice the difference to m1d + void m1d(@A Outer.Inner.Inner2 p1d) {} + + // m2a-b both have the same parameter type. + void m2a(@A Inner.Inner2 p2a) {} + void m2b(Outer.@A Inner.Inner2 p2b) {} + + // The location for @A is the same in m3a-c + void m3a(@A Outer p3a) {} + void m3b(@A Outer.Inner p3b) {} + void m3c(@A Outer.Inner.Inner2 p3c) {} + + // Test combinations + void m4a(@A Outer p3a) {} + void m4b(@A Outer. @B Inner p3b) {} + void m4c(@A Outer. @B Inner. @C Inner2 p3c) {} + } + } + + void m4a(@A Map p4a) {} + void m4b(Map.@B Entry p4c) {} + // Illegal: + // void m4b(@A Map.Entry p4b) {} + // void m4c(@A Map.@B Entry p4c) {} + + void m4c(Map.@B Entry p4d) {} + // Illegal: + // void m4d(@A Map.@B Entry p4d) {} + + void m4e(MyList p4e) {} + void m4f(MyList p4f) {} + // Illegal: + // void m4g(MyList<@A Map.Entry> p4e) {} + // void m4h(MyList<@A Map.@B Entry> p4f) {} + + class GInner { + class GInner2 {} + } + + static class Static {} + static class GStatic { + static class GStatic2 {} + } +} + +class Test1 { + // Outer.GStatic.GStatic2 gs; + Outer.GStatic.@A GStatic2 gsgood; + // TODO: add failing test + // Outer.@A GStatic.GStatic2 gsbad; + + MyList<@A Outer . @B Inner. @C Inner2> f; + @A Outer .GInner.GInner2 g; + + // TODO: Make sure that something like this fails gracefully: + // MyList pkg; + + @A Outer f1; + @A Outer . @B Inner f2 = f1.new @B Inner(); + // TODO: ensure type annos on new are stored. + @A Outer . @B GInner<@C Object> f3 = f1.new @B GInner<@C Object>(); + + MyList<@A Outer . @B GInner<@C MyList<@D Object>>. @E GInner2<@F Integer, @G Object>> f4; + // MyList.GInner2> f4clean; + + @A Outer . @B GInner<@C MyList<@D Object>>. @E GInner2<@F Integer, @G Object> f4top; + + MyList<@A Outer . @B GInner<@C MyList<@D Object @E[] @F[]>>. @G GInner2<@H Integer, @I Object> @J[] @K[]> f4arr; + + @A Outer . @B GInner<@C MyList<@D Object @E[] @F[]>>. @G GInner2<@H Integer, @I Object> @J[] @K[] f4arrtop; + + MyList f5; + // Illegal: + // MyList<@A Outer . @B Static> f5; + + Outer . @B Static f6; + // Illegal: + // @A Outer . @B Static f6; + + Outer . @Bv("B") GStatic<@Cv("C") String, @Dv("D") Object> f7; + // Illegal: + // @Av("A") Outer . @Bv("B") GStatic<@Cv("C") String, @Dv("D") Object> f7; + + Outer . @Cv("Data") Static f8; + // Illegal: + // @A Outer . @Cv("Data") Static f8; + + MyList f9; + // Illegal: + // MyList<@A Outer . @Cv("Data") Static> f9; +} + +class Test2 { + void m() { + @A Outer f1 = null; + @A Outer.@B Inner f2 = null; + Outer.@B Static f3 = null; + // Illegal: + // @A Outer.@B Static f3 = null; + @A Outer.@C Inner f4 = null; + + Outer . @B Static f5 = null; + Outer . @Cv("Data") Static f6 = null; + MyList f7 = null; + } +} + +class Test3 { + void monster(@A Outer p1, + @A Outer.@B Inner p2, + Outer.@B Static p3, + @A Outer.@Cv("Test") Inner p4, + Outer . @B Static p5, + Outer . @Cv("Data") Static p6, + MyList p7) { + } +} + +class Test4 { + void m() { + @A Outer p1 = new @A Outer(); + @A Outer.@B Inner p2 = p1.new @B Inner(); + // Illegal: + // @A Outer.@B Static p3 = new @A Outer.@B Static(); + // Object o3 = new @A Outer.@B Static(); + + @A Outer.@Cv("Test") Inner p4 = p1.new @Cv("Test") Inner(); + Outer . @B Static p5 = new Outer . @B Static(); + Outer . @Cv("Data") Static p6 = new Outer . @Cv("Data") Static(); + MyList p7 = new MyList(); + } +} + +class MyList { } + + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface C { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface D { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface E { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface F { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface G { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface H { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface I { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface J { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface K { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Av { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Bv { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Cv { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Dv { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Ev { String value(); } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface Fv { String value(); } + diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Parameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Parameters.java new file mode 100644 index 00000000000..4952986d347 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Parameters.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: parameter type array/generics + * @author Mahmood Ali + * @compile Parameters.java + */ + +class Parameters { + void unannotated(Parameterized a) {} + void firstTypeArg(Parameterized<@A String, String> a) {} + void secondTypeArg(Parameterized a) {} + void bothTypeArgs(Parameterized<@A String, @B String> both) {} + + void nestedParameterized(Parameterized<@A Parameterized<@A String, @B String>, @B String> a) {} + + void array1(@A String [] a) {} + void array1Deep(@A String @B [] a) {} + void array2(@A String [] [] a) {} + void array2Deep(@A String @A [] @B [] a) {} + void array2First(String @A [] [] a) {} + void array2Second(String [] @B [] a) {} +} + +class Parameterized { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java new file mode 100644 index 00000000000..95103ff1670 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Receivers.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: receivers + * @author Mahmood Ali, Werner Dietl + * @compile Receivers.java + */ +class DefaultUnmodified { + void plain(@A DefaultUnmodified this) { } + void generic(@A DefaultUnmodified this) { } + void withException(@A DefaultUnmodified this) throws Exception { } + String nonVoid(@A DefaultUnmodified this) { return null; } + void accept(@A DefaultUnmodified this, T r) throws Exception { } +} + +class PublicModified { + public final void plain(@A PublicModified this) { } + public final void generic(@A PublicModified this) { } + public final void withException(@A PublicModified this) throws Exception { } + public final String nonVoid(@A PublicModified this) { return null; } + public final void accept(@A PublicModified this, T r) throws Exception { } +} + +class WithValue { + void plain(@B("m") WithValue this) { } + void generic(@B("m") WithValue this) { } + void withException(@B("m") WithValue this) throws Exception { } + String nonVoid(@B("m") WithValue this) { return null; } + void accept(@B("m") WithValue this, T r) throws Exception { } +} + +class WithFinal { + void plain(final @B("m") WithFinal this) { } + void generic(final @B("m") WithFinal this) { } + void withException(final @B("m") WithFinal this) throws Exception { } + String nonVoid(final @B("m") WithFinal this) { return null; } + void accept(final @B("m") WithFinal this, T r) throws Exception { } +} + +class WithBody { + Object f; + + void field(@A WithBody this) { + this.f = null; + } + void meth(@A WithBody this) { + this.toString(); + } +} + +class Generic1 { + void test1(Generic1 this) {} + void test2(@A Generic1 this) {} + void test3(Generic1<@A X> this) {} + void test4(@A Generic1<@A X> this) {} +} + +class Generic2<@A X> { + void test1(Generic2 this) {} + void test2(@A Generic2 this) {} + void test3(Generic2<@A X> this) {} + void test4(@A Generic2<@A X> this) {} +} + +class Generic3 { + void test1(Generic3 this) {} + void test2(@A Generic3 this) {} + void test3(Generic3<@A X> this) {} + void test4(@A Generic3<@A X> this) {} +} + +class Generic4 { + void test1(Generic4 this) {} + void test2(@A Generic4 this) {} + void test3(Generic4<@A X> this) {} + void test4(@A Generic4<@A X> this) {} +} + +class Outer { + class Inner { + void none(Outer.Inner this) {} + void outer(@A Outer.Inner this) {} + void inner(Outer. @B("i") Inner this) {} + void both(@A Outer.@B("i") Inner this) {} + + void innerOnlyNone(Inner this) {} + void innerOnly(@A Inner this) {} + } +} + +class GenericOuter { + class GenericInner { + void none(GenericOuter.GenericInner this) {} + void outer(@A GenericOuter.GenericInner this) {} + void inner(GenericOuter. @B("i") GenericInner this) {} + void both(@A GenericOuter.@B("i") GenericInner this) {} + + void innerOnlyNone(GenericInner this) {} + void innerOnly(@A GenericInner this) {} + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java new file mode 100644 index 00000000000..3aecc7a9219 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2012, 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.lang.annotation.*; + +/* + * @test + * @bug 8006775 + * @summary repeating type annotations are possible + * @author Werner Dietl + * @compile/fail/ref=RepeatingTypeAnnotations.out -XDrawDiagnostics RepeatingTypeAnnotations.java + */ + +class RepeatingTypeAnnotations { + // Fields + @RTA @RTA Object fr1 = null; + Object fr2 = new @RTA @RTA Object(); + // error + Object fs = new @TA @TA Object(); + // error + Object ft = new @TA @TA Object(); + Object fe = new @TA @TA Object(); + + // Local variables + Object foo() { + Object o = new @RTA @RTA Object(); + o = new @TA @RTA @RTA Object(); + o = new @RTA @TA @RTA Object(); + // error + o = new @RTA @TA @RTA @TA Object(); + // error + return new @TA @TA Object(); + } + + // Instance creation + Object bar() { + Object o = new @RTA @RTA MyList<@RTA @RTA Object>(); + o = new @TA @RTA MyList<@TA @RTA Object>(); + o = new @TA @RTA @RTA MyList<@RTA @TA @RTA Object>(); + // error + o = new @TA @TA MyList<@RTA @RTA Object>(); + // error + o = new @RTA @RTA MyList<@TA @TA Object>(); + // error + return new @TA @TA MyList<@RTA @RTA Object>(); + } + + // More tests + void oneArg() { + Object o = new @RTA @RTA Object(); + // error + o = new @TA @TA Object(); + o = new @RTA @TA @RTA Object(); + + o = new MyList<@RTA @RTA Object>(); + // error + o = new MyList<@TA @TA Object>(); + // error + o = new @TA @TA MyList<@TA @TA Object>(); + // error + this.<@TA @TA String>newList(); + + this.<@RTA @RTA MyList<@RTA @RTA String>>newList(); + // error + this.<@TA @TA MyList<@TA @TA String>>newList(); + + o = (@RTA @RTA MyList<@RTA @RTA Object>) o; + // error + o = (@TA @TA MyList<@TA @TA Object>) o; + + this.<@RTA @RTA String, @RTA @RTA Object>newMap(); + // error + this.<@TA @TA String, @TA @TA Object>newMap(); + + this.<@RTA @RTA String @RTA @RTA []>newList(); + // error + this.<@TA @TA String @TA @TA []>newList(); + + this.<@RTA @RTA String @RTA @RTA [] @RTA @RTA [], MyList<@RTA @RTA String> @RTA @RTA []>newMap(); + // error + this. @TA @TA []>newMap(); + } + + static void newList() { } + static void newMap() { } +} + +class MyList { } + + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface TA { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface TAs { + TA[] value(); +} + +@Repeatable(RTAs.class) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface RTA { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface RTAs { + RTA[] value(); +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.out b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.out new file mode 100644 index 00000000000..4866c6ef697 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.out @@ -0,0 +1,53 @@ +RepeatingTypeAnnotations.java:39:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:39:25: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:41:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:41:25: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:42:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:42:25: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:50:22: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:50:31: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:52:20: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:52:24: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:61:17: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:61:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:63:34: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:63:38: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:65:20: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:65:24: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:72:17: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:72:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:77:24: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:77:28: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:79:17: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:79:21: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:79:32: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:79:36: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:81:15: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:81:19: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:85:15: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:85:19: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:85:30: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:85:34: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:89:14: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:89:18: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:89:29: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:89:33: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:93:15: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:93:19: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:93:31: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:93:35: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:97:30: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:97:34: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:97:15: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:97:19: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:22: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:26: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:33: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:37: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:68: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:72: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:52: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +RepeatingTypeAnnotations.java:101:56: compiler.err.duplicate.annotation.missing.container: TA, java.lang.annotation.Repeatable +- compiler.note.unchecked.filename: RepeatingTypeAnnotations.java +- compiler.note.unchecked.recompile +50 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ResourceVariables.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ResourceVariables.java new file mode 100644 index 00000000000..7482e043f51 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/ResourceVariables.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 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.lang.annotation.*; + +import java.io.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: resource variables + * @author Werner Dietl + * @compile ResourceVariables.java + */ + +class ResourceVariables { + void m() throws Exception { + try (@A InputStream is = new @B FileInputStream("xxx")) { + } + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Throws.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Throws.java new file mode 100644 index 00000000000..147325a0214 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Throws.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: throw clauses + * @author Mahmood Ali + * @compile Throws.java + */ +class DefaultUnmodified { + void oneException() throws @A Exception {} + void twoExceptions() throws @A RuntimeException, @A Exception {} +} + +class PublicModified { + public final void oneException(String a) throws @A Exception {} + public final void twoExceptions(String a) throws @A RuntimeException, @A Exception {} +} + +class WithValue { + void oneException() throws @B("m") Exception {} + void twoExceptions() throws @B(value="m") RuntimeException, @A Exception {} +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A {} +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TopLevelBlocks.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TopLevelBlocks.java new file mode 100644 index 00000000000..ee2a6710ca6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TopLevelBlocks.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 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.lang.annotation.*; +import java.util.Map; + +/* + * @test + * @bug 8006775 + * @summary type annotation location: top level blocks + * @author Werner Dietl + * @compile TopLevelBlocks.java + */ + +class TopLevelBlocks { + static Object f; + + { + f = new @A Object(); + } + + static final Object sf; + + static { + sf = new @A Object(); + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeCasts.java new file mode 100644 index 00000000000..c7508e25451 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeCasts.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: type casts + * @author Mahmood Ali + * @compile TypeCasts.java + */ +class TypeCasts { + void methodA() { + String s = (@A String) null; + Object o = (@A Class<@A String>) null; + } + + void methodB() { + String s = (@B("m") String) null; + Object o = (@B("m") Class<@B("m") String>) null; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeParameters.java new file mode 100644 index 00000000000..1e93ba54639 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/TypeParameters.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: class and method type parameters + * @author Mahmood Ali + * @compile TypeParameters.java + */ + +class Unannotated { } +class OneAnnotated<@A K> { } +class TwoAnnotated<@A K, @A V> { } +class SecondAnnotated { } + +class TestMethods { + void unannotated() { } + <@A K> void oneAnnotated() { } + <@A K, @B("m") V> void twoAnnotated() { } + void secondAnnotated() { } +} + +class UnannotatedB { } +class OneAnnotatedB<@B("m") K> { } +class TwoAnnotatedB<@B("m") K, @B("m") V> { } +class SecondAnnotatedB { } + +class OneAnnotatedC<@C K> { } +class TwoAnnotatedC<@C K, @C V> { } +class SecondAnnotatedC { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } +@Target(ElementType.TYPE_USE) +@interface C { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java new file mode 100644 index 00000000000..e0c3082ebb6 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 test acceptance of varargs annotations + * @author Mahmood Ali + * @compile Varargs.java + */ + +import java.lang.annotation.*; + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A {} + +class Varargs { + + // Handle annotations on a varargs element type + void varargPlain(Object @A... objs) { + + } + + void varargGeneric(Class @A ... clz) { + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Wildcards.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Wildcards.java new file mode 100644 index 00000000000..38de895a767 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Wildcards.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.annotation.*; + +/* + * @test + * @bug 6843077 8006775 + * @summary new type annotation location: wildcard bound + * @author Mahmood Ali + * @compile Wildcards.java + */ +class BoundTest { + void wcExtends(MyList l) { } + void wcSuper(MyList l) { } + + MyList returnWcExtends() { return null; } + MyList returnWcSuper() { return null; } + MyList> complex() { return null; } +} + +class BoundWithValue { + void wcExtends(MyList l) { } + void wcSuper(MyList l) { } + + MyList returnWcExtends() { return null; } + MyList returnWcSuper() { return null; } + MyList> complex() { return null; } +} + +class SelfTest { + void wcExtends(MyList<@A ?> l) { } + void wcSuper(MyList<@A ?> l) { } + + MyList<@A ?> returnWcExtends() { return null; } + MyList<@A ?> returnWcSuper() { return null; } + MyList<@A ? extends @A MyList<@B("m") ?>> complex() { return null; } +} + +class SelfWithValue { + void wcExtends(MyList<@B("m") ?> l) { } + void wcSuper(MyList<@B(value="m") ?> l) { } + + MyList<@B("m") ?> returnWcExtends() { return null; } + MyList<@B(value="m") ?> returnWcSuper() { return null; } + MyList<@B("m") ? extends MyList<@B("m") ? super String>> complex() { return null; } +} + +class MyList { } + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface A { } +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface B { String value(); } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java new file mode 100644 index 00000000000..02e20ad3b19 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.util.HashSet; +import java.util.Set; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.lang.model.util.ElementFilter; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePath; +import com.sun.tools.javac.main.JavaCompiler; +import com.sun.tools.javac.main.JavaCompiler.CompileState; +import com.sun.tools.javac.processing.JavacProcessingEnvironment; +import com.sun.tools.javac.util.Context; + +/* + * @test + * @summary test that package annotations are available to type processors. + * This class implements the functionality of a type processor, as previously + * embodied by the AbstractTypeProcessor class. + * + * @author Mahmood Ali + * @author Werner Dietl + * + * @compile PackageProcessor.java + * @compile -cp . -processor PackageProcessor mypackage/Anno.java mypackage/MyClass.java mypackage/package-info.java + */ + +@SupportedAnnotationTypes("*") +public class PackageProcessor extends AbstractProcessor { + + private final AttributionTaskListener listener = new AttributionTaskListener(); + private final Set elements = new HashSet(); + + @Override + public final void init(ProcessingEnvironment env) { + super.init(env); + JavacTask.instance(env).addTaskListener(listener); + Context ctx = ((JavacProcessingEnvironment)processingEnv).getContext(); + JavaCompiler compiler = JavaCompiler.instance(ctx); + compiler.shouldStopPolicyIfNoError = CompileState.max(compiler.shouldStopPolicyIfNoError, + CompileState.FLOW); + } + + @Override + public final boolean process(Set annotations, + RoundEnvironment roundEnv) { + for (TypeElement elem : ElementFilter.typesIn(roundEnv.getRootElements())) { + elements.add(elem.getQualifiedName()); + } + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + private final class AttributionTaskListener implements TaskListener { + @Override + public void started(TaskEvent e) { } + + @Override + public void finished(TaskEvent e) { + if (e.getKind() != TaskEvent.Kind.ANALYZE) + return; + + if (!elements.remove(e.getTypeElement().getQualifiedName())) + return; + + if (e.getTypeElement().getSimpleName().contentEquals("MyClass")) { + Element owner = e.getTypeElement().getEnclosingElement(); + if (owner.getKind() != ElementKind.PACKAGE) + throw new RuntimeException("class owner should be a package: " + owner); + if (owner.getAnnotationMirrors().size() != 1) + throw new RuntimeException("the owner package should have one annotation: " + owner); + } + } + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java new file mode 100644 index 00000000000..901cb6c9850 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 mypackage; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Anno {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java new file mode 100644 index 00000000000..98f9e433880 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 mypackage; + +public class MyClass {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java new file mode 100644 index 00000000000..bcd7fb672e8 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +@mypackage.Anno +package mypackage; diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java new file mode 100644 index 00000000000..4d5f2db0a12 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for class extends clauses + * @compile -g Driver.java ReferenceInfoUtil.java ClassExtends.java + * @run main Driver ClassExtends + */ +public class ClassExtends { + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1), + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1) + }) + public String regularClass() { + return "class Test extends @TA Object implements Cloneable, @TB Runnable {" + + " public void run() { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1, + genericLocation = { 3, 1 }) + }) + public String regularClassExtendsParametrized() { + return "class Test extends HashMap<@TA String, String> implements Cloneable, Map{ } "; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1), + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1) + }) + public String abstractClass() { + return "abstract class Test extends @TA Date implements Cloneable, @TB Runnable {" + + " public void run() { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_EXTENDS, typeIndex = -1, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1, + genericLocation = { 3, 1 }) + }) + public String abstractClassExtendsParametrized() { + return "abstract class Test extends HashMap<@TA String, String> implements Cloneable, Map{ } "; + } + + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1) + public String regularInterface() { + return "interface Test extends Cloneable, @TB Runnable { }"; + } + + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1, + genericLocation = { 3, 1 }) + public String regularInterfaceExtendsParametrized() { + return "interface Test extends Cloneable, Map{ } "; + } + + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1) + public String regularEnum() { + return "enum Test implements Cloneable, @TB Runnable { TEST; public void run() { } }"; + } + + @TADescription(annotation = "TB", type = CLASS_EXTENDS, typeIndex = 1, + genericLocation = { 3, 0 }) + public String regularEnumExtendsParametrized() { + return + "enum Test implements Cloneable, Comparator<@TB String> { TEST; " + + "public int compare(String a, String b) { return 0; }}"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java new file mode 100644 index 00000000000..2fca8089824 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for class type parameters + * @compile -g Driver.java ReferenceInfoUtil.java ClassTypeParam.java + * @run main Driver ClassTypeParam + */ +public class ClassTypeParam { + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularClass() { + return "class Test<@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularClass2() { + return "class Test<@TA K extends @TB Date, @TC V extends @TE Cloneable> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}) + }) + public String regularClassParameterized() { + return "class Test, V extends @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TG", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0) + }) + public String regularClassParameterized2() { + return "class Test, V extends @TF Object & @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String abstractClass() { + return "abstract class Test<@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0) + }) + public String abstractClassParameterized() { + return "abstract class Test, V extends @TF Object & @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularInterface() { + return "interface Test<@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}) + }) + public String regularInterfaceParameterized() { + return "interface Test, V extends @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TG", type = CLASS_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0) + }) + public String regularInterfaceParameterized2() { + return "interface Test, V extends @TF Object & @TC List<@TD List<@TE Object>>> { }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String useInReturn1() { + return "class Test { @TA T m() { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {3, 0}) + public String useInReturn2() { + return "class Test { Class<@TA T> m() { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, genericLocation = {3, 0}) + public String useInParam1() { + return "class Test { void m(Class<@TA T> p) { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, genericLocation = {3, 0}) + public String useInParam2() { + return "class Test { void m(Class<@TA Object> p) { throw new RuntimeException(); } }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java new file mode 100644 index 00000000000..bbdcba3f319 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for constructor results + * @compile -g Driver.java ReferenceInfoUtil.java Constructors.java + * @run main Driver Constructors + */ +public class Constructors { + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + }) + public String regularClass() { + return "class Test { @TA Test() {}" + + " @TB Test(@TC int b) {} }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + }) + @TestClass("Test$Inner") + public String innerClass() { + return "class Test { class Inner {" + + " @TA Inner() {}" + + " @TB Inner(@TC int b) {}" + + " } }"; + } + + /* TODO: Outer.this annotation support. + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RECEIVER), + @TADescription(annotation = "TB", type = METHOD_RETURN), + @TADescription(annotation = "TC", type = METHOD_RECEIVER), + @TADescription(annotation = "TD", type = METHOD_RETURN), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + }) + @TestClass("Test$Inner") + public String innerClass2() { + return "class Test { class Inner {" + + " @TB Inner(@TA Test Test.this) {}" + + " @TD Inner(@TC Test Test.this, @TE int b) {}" + + " } }"; + } + */ +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java new file mode 100644 index 00000000000..042b7b0b1db --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2009, 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.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.TypeAnnotation; +import com.sun.tools.classfile.TypeAnnotation.TargetType; + +public class Driver { + + private static final PrintStream out = System.out; + + public static void main(String[] args) throws Exception { + if (args.length == 0 || args.length > 1) + throw new IllegalArgumentException("Usage: java Driver "); + String name = args[0]; + Class clazz = Class.forName(name); + new Driver().runDriver(clazz.newInstance()); + } + + protected void runDriver(Object object) throws Exception { + int passed = 0, failed = 0; + Class clazz = object.getClass(); + out.println("Tests for " + clazz.getName()); + + // Find methods + for (Method method : clazz.getMethods()) { + Map expected = expectedOf(method); + if (expected == null) + continue; + if (method.getReturnType() != String.class) + throw new IllegalArgumentException("Test method needs to return a string: " + method); + String testClass = testClassOf(method); + + try { + String compact = (String)method.invoke(object); + String fullFile = wrap(compact); + ClassFile cf = compileAndReturn(fullFile, testClass); + List actual = ReferenceInfoUtil.extendedAnnotationsOf(cf); + ReferenceInfoUtil.compare(expected, actual, cf); + out.println("PASSED: " + method.getName()); + ++passed; + } catch (Throwable e) { + out.println("FAILED: " + method.getName()); + out.println(" " + e.toString()); + ++failed; + } + } + + out.println(); + int total = passed + failed; + out.println(total + " total tests: " + passed + " PASSED, " + failed + " FAILED"); + + out.flush(); + + if (failed != 0) + throw new RuntimeException(failed + " tests failed"); + } + + private Map expectedOf(Method m) { + TADescription ta = m.getAnnotation(TADescription.class); + TADescriptions tas = m.getAnnotation(TADescriptions.class); + + if (ta == null && tas == null) + return null; + + Map result = + new HashMap(); + + if (ta != null) + result.putAll(expectedOf(ta)); + + if (tas != null) { + for (TADescription a : tas.value()) { + result.putAll(expectedOf(a)); + } + } + + return result; + } + + private Map expectedOf(TADescription d) { + String annoName = d.annotation(); + + TypeAnnotation.Position p = new TypeAnnotation.Position(); + p.type = d.type(); + if (d.offset() != NOT_SET) + p.offset = d.offset(); + if (d.lvarOffset().length != 0) + p.lvarOffset = d.lvarOffset(); + if (d.lvarLength().length != 0) + p.lvarLength = d.lvarLength(); + if (d.lvarIndex().length != 0) + p.lvarIndex = d.lvarIndex(); + if (d.boundIndex() != NOT_SET) + p.bound_index = d.boundIndex(); + if (d.paramIndex() != NOT_SET) + p.parameter_index = d.paramIndex(); + if (d.typeIndex() != NOT_SET) + p.type_index = d.typeIndex(); + if (d.exceptionIndex() != NOT_SET) + p.exception_index = d.exceptionIndex(); + if (d.genericLocation().length != 0) { + p.location = TypeAnnotation.Position.getTypePathFromBinary(wrapIntArray(d.genericLocation())); + } + + return Collections.singletonMap(annoName, p); + } + + private List wrapIntArray(int[] ints) { + List list = new ArrayList(ints.length); + for (int i : ints) + list.add(i); + return list; + } + + private String testClassOf(Method m) { + TestClass tc = m.getAnnotation(TestClass.class); + if (tc != null) { + return tc.value(); + } else { + return "Test"; + } + } + + private ClassFile compileAndReturn(String fullFile, String testClass) throws Exception { + File source = writeTestFile(fullFile); + File clazzFile = compileTestFile(source, testClass); + return ClassFile.read(clazzFile); + } + + protected File writeTestFile(String fullFile) throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println(fullFile); + out.close(); + return f; + } + + protected File compileTestFile(File f, String testClass) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path; + if (f.getParent() != null) { + path = f.getParent(); + } else { + path = ""; + } + + return new File(path + testClass + ".class"); + } + + private String wrap(String compact) { + StringBuilder sb = new StringBuilder(); + + // Automatically import java.util + sb.append("\nimport java.util.*;"); + sb.append("\nimport java.lang.annotation.*;"); + + sb.append("\n\n"); + boolean isSnippet = !(compact.startsWith("class") + || compact.contains(" class")) + && !compact.contains("interface") + && !compact.contains("enum"); + if (isSnippet) + sb.append("class Test {\n"); + + sb.append(compact); + sb.append("\n"); + + if (isSnippet) + sb.append("}\n\n"); + + if (isSnippet) { + // Have a few common nested types for testing + sb.append("class Outer { class Inner {} }"); + sb.append("class SOuter { static class SInner {} }"); + sb.append("class GOuter { class GInner {} }"); + } + + // create A ... F annotation declarations + sb.append("\n@interface A {}"); + sb.append("\n@interface B {}"); + sb.append("\n@interface C {}"); + sb.append("\n@interface D {}"); + sb.append("\n@interface E {}"); + sb.append("\n@interface F {}"); + + // create TA ... TF proper type annotations + sb.append("\n"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TA {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TB {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TC {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TD {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TE {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TF {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TG {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TH {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TI {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TJ {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TK {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TL {}"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TM {}"); + + // create RTA, RTAs, RTB, RTBs for repeating type annotations + sb.append("\n"); + sb.append("\n@Repeatable(RTAs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTA {}"); + sb.append("\n@Repeatable(RTBs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTB {}"); + + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); }"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTBs { RTB[] value(); }"); + + sb.append("\n@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})"); + sb.append("\n@interface Decl {}"); + + return sb.toString(); + } + + public static final int NOT_SET = -888; + +} + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@interface TADescription { + String annotation(); + + TargetType type(); + int offset() default Driver.NOT_SET; + int[] lvarOffset() default { }; + int[] lvarLength() default { }; + int[] lvarIndex() default { }; + int boundIndex() default Driver.NOT_SET; + int paramIndex() default Driver.NOT_SET; + int typeIndex() default Driver.NOT_SET; + int exceptionIndex() default Driver.NOT_SET; + + int[] genericLocation() default {}; +} + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@interface TADescriptions { + TADescription[] value() default {}; +} + +/** + * The name of the class that should be analyzed. + * Should only need to be provided when analyzing inner classes. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@interface TestClass { + String value() default "Test"; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java new file mode 100644 index 00000000000..a7c2818cf5d --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 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 static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for exception parameters + * @author Werner Dietl + * @compile -g Driver.java ReferenceInfoUtil.java ExceptionParameters.java + * @run main Driver ExceptionParameters + */ +public class ExceptionParameters { + + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0) + public String exception() { + return "void exception() { try { new Object(); } catch(@TA Exception e) { } }"; + } + + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0) + public String finalException() { + return "void finalException() { try { new Object(); } catch(final @TA Exception e) { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0), + @TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1), + @TADescription(annotation = "TC", type = EXCEPTION_PARAMETER, exceptionIndex = 2) + }) + public String multipleExceptions() { + return "void multipleExceptions() { " + + "try { new Object(); } catch(@TA Exception e) { }" + + "try { new Object(); } catch(@TB Exception e) { }" + + "try { new Object(); } catch(@TC Exception e) { }" + + " }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java new file mode 100644 index 00000000000..91bc6496a98 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for field + * @compile -g Driver.java ReferenceInfoUtil.java Fields.java + * @run main Driver Fields + */ +public class Fields { + + // field types + @TADescription(annotation = "TA", type = FIELD) + public String fieldAsPrimitive() { + return "@TA int test;"; + } + + @TADescription(annotation = "TA", type = FIELD) + public String fieldAsObject() { + return "@TA Object test;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = { 3, 1, 3, 0 }) + }) + public String fieldAsParametrized() { + return "@TA Map<@TB String, @TC List<@TD String>> test;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 0, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 0, 0, 0, 0 }) + }) + public String fieldAsArray() { + return "@TC String @TA [] @TB [] test;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 0, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 0, 0, 0, 0 }) + }) + public String fieldAsArrayOld() { + return "@TC String test @TA [] @TB [];"; + } + + @TADescriptions({}) + public String fieldWithDeclarationAnnotatin() { + return "@Decl String test;"; + } + + @TADescriptions({}) + public String fieldWithNoTargetAnno() { + return "@A String test;"; + } + + // Smoke tests + @TADescription(annotation = "TA", type = FIELD) + public String interfacefieldAsObject() { + return "interface Test { @TA String test = null; }"; + } + + @TADescription(annotation = "TA", type = FIELD) + public String abstractfieldAsObject() { + return "abstract class Test { @TA String test; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = { 3, 1, 3, 0 }) + }) + public String interfacefieldAsParametrized() { + return "interface Test { @TA Map<@TB String, @TC List<@TD String>> test = null; }"; + } + + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = { 3, 1, 3, 0 }) + }) + public String staticFieldAsParametrized() { + return "static @TA Map<@TB String, @TC List<@TD String>> test;"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java new file mode 100644 index 00000000000..c3006390219 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test that the examples from the manual are stored as expected + * @compile -g Driver.java ReferenceInfoUtil.java FromSpecification.java + * @run main Driver FromSpecification + */ +public class FromSpecification { + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 2, 0}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 1}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 1, 3, 0}, paramIndex = 0) + }) + public String testSpec1() { + return "void test(@TA Map<@TB ? extends @TC String, @TD List<@TE Object>> a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 0, 0}, paramIndex = 0) + }) + public String testSpec2() { + return "void test(@TI String @TF [] @TG [] @TH [] a) { }"; + } + + // Note first "1, 0" for top-level class Test. + @TADescriptions({ + @TADescription(annotation = "TJ", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TK", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TL", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TM", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testSpec3() { + return "class Test { class O1 { class O2 { class O3 { class NestedStatic {} } } }" + + "void test(@TM O1.@TL O2.@TK O3.@TJ NestedStatic a) { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 3, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 3, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 3, 0, 0, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 1}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 1, 3, 0}, paramIndex = 0) + }) + public String testSpec4() { + return "void test(@TA Map<@TB Comparable<@TF Object @TC [] @TD [] @TE []>, @TG List<@TH String>> a) { }"; + } + + // Note first "1, 0" for top-level class Test. + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0, 1, 0, 3, 1}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0, 1, 0, 3, 1}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testSpec5() { + return "class Test { class O1 { class O2 { class O3 { class Nested {} } } }" + + "void test(@TH O1.@TE O2<@TF String, @TG String>.@TD O3.@TA Nested<@TB String, @TC String> a) { } }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java new file mode 100644 index 00000000000..c23636c2f82 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method parameters + * @compile -g Driver.java ReferenceInfoUtil.java MethodParameters.java + * @run main Driver MethodParameters + */ +public class MethodParameters { + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + public String methodParamAsPrimitive() { + return "void test(@TA int a) { }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) + public String methodParamAsObject() { + return "void test(Object b, @TA Object a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1 }, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0 }, paramIndex = 0) + }) + public String methodParamAsParametrized() { + return "void test(@TA Map<@TB String, @TC List<@TD String>> a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 0, 2, 0 }, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1 }, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0 }, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0, 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0, 3, 0, 2, 0 }, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0, 3, 1 }, paramIndex = 0), + @TADescription(annotation = "TJ", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0, 2, 0, 3, 1, 2, 0 }, paramIndex = 0) + }) + public String methodParamAsWildcard() { + return "void test(@TA Map<@TB ? extends @TC String," + + " @TD List<@TE ? extends @TF Map<@TG ? super @TH String," + + " @TI ? extends @TJ Object>>> a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0 }, paramIndex = 1), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0, 0, 0 }, paramIndex = 1) + }) + public String methodParamAsArray() { + return "void test(Object b, @TC String @TA [] @TB [] a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0 }, paramIndex = 1), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0, 0, 0 }, paramIndex = 1) + }) + public String methodParamAsVararg() { + return "void test(Object b, @TC String @TA [] @TB ... a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0 }, paramIndex = 1), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 0, 0, 0, 0 }, paramIndex = 1) + }) + public String methodParamAsFQVararg() { + return "void test(Object b, java.lang.@TC String @TA [] @TB ... a) { }"; + } + + @TADescriptions({}) + public String methodWithDeclarationAnnotatin() { + return "void test(@Decl String a) { }"; + } + + @TADescriptions({}) + public String methodWithNoTargetAnno() { + return "void test(@A String a) { }"; + } + + // Smoke tests + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + public String interfacemethodParamAsObject() { + return "interface Test { void test(@TA Object a); }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 2) + public String abstractmethodParamAsObject() { + return "abstract class Test { abstract void test(Object b, Object c, @TA Object a); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 0 }, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1 }, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = { 3, 1, 3, 0 }, paramIndex = 0) + }) + public String interfacemethodParamAsParametrized() { + return "interface Test { void test(@TA Map<@TB String, @TC List<@TD String>> a); }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java new file mode 100644 index 00000000000..dc19f8d12fd --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method receivers + * @compile -g Driver.java ReferenceInfoUtil.java MethodReceivers.java + * @run main Driver MethodReceivers + */ +public class MethodReceivers { + + @TADescription(annotation = "TA", type = METHOD_RECEIVER) + public String regularMethod() { + return "class Test { void test(@TA Test this) { } }"; + } + + @TADescription(annotation = "TA", type = METHOD_RECEIVER) + public String abstractMethod() { + return "abstract class Test { abstract void test(@TA Test this); }"; + } + + @TADescription(annotation = "TA", type = METHOD_RECEIVER) + public String interfaceMethod() { + return "interface Test { void test(@TA Test this); }"; + } + + @TADescription(annotation = "TA", type = METHOD_RECEIVER) + public String regularWithThrows() { + return "class Test { void test(@TA Test this) throws Exception { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RECEIVER, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_RECEIVER, + genericLocation = {1, 0}) + }) + @TestClass("TestOuter$TestInner") + public String nestedtypes1() { + return "class TestOuter { class TestInner { void test(@TA TestOuter. @TB TestInner this) { } } }"; + } + + @TADescription(annotation = "TA", type = METHOD_RECEIVER, + genericLocation = {}) + @TestClass("TestOuter$TestInner") + public String nestedtypes2() { + return "class TestOuter { class TestInner { void test(@TA TestOuter.TestInner this) { } } }"; + } + + @TADescription(annotation = "TB", type = METHOD_RECEIVER, + genericLocation = {1, 0}) + @TestClass("TestOuter$TestInner") + public String nestedtypes3() { + return "class TestOuter { class TestInner { void test(TestOuter. @TB TestInner this) { } } }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java new file mode 100644 index 00000000000..b6946817666 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method return + * @compile -g Driver.java ReferenceInfoUtil.java MethodReturns.java + * @run main Driver MethodReturns + */ +public class MethodReturns { + + // Method returns + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String methodReturnAsPrimitive() { + return "@TA int test() { return 0; }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String methodReturnAsObject() { + return "@TA Object test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = { 3, 1, 3, 0 }) + }) + public String methodReturnAsParametrized() { + return "@TA Map<@TB String, @TC List<@TD String>> test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 0, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 0, 0, 0, 0 }) + }) + public String methodReturnAsArray() { + return "@TC String @TA [] @TB [] test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 0, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 0, 0, 0, 0 }) + }) + public String methodReturnAsArrayOld() { + return "@TC String test() @TA [] @TB [] { return null; }"; + } + + @TADescriptions({}) + public String methodWithDeclarationAnnotation() { + return "@Decl String test() { return null; }"; + } + + @TADescriptions({}) + public String methodWithNoTargetAnno() { + return "@A String test() { return null; }"; + } + + // Smoke tests + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String interfaceMethodReturnAsObject() { + return "interface Test { @TA Object test(); }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String abstractMethodReturnAsObject() { + return "abstract class Test { abstract @TA Object test(); }"; + } + + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 1 }), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = { 3, 1, 3, 0 }) + }) + public String interfaceMethodReturnAsParametrized() { + return "interface Test { @TA Map<@TB String, @TC List<@TD String>> test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = { 3, 0 }), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 0 }), + @TADescription(annotation = "TE", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 1 }), + @TADescription(annotation = "TF", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 1, 2, 0 }) + }) + public String methodReturnAsNestedWildcard() { + return "Set<@TA ? extends @TB GOuter. @TC GInner<@TD String, @TE ? super @TF Object>> entrySet() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = { 3, 0, 1, 0, 3, 0 }), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 1, 0, 3, 1 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 1, 0, 3, 1, 2, 0 }) + }) + public String methodReturnAsNestedWildcard2() { + return "class GOuter { class GInner {} } " + + "class Test { Set.GInner<@TA K, @TB ? extends @TC Object>> entrySet() { return null; } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + }) + public String methodReturnAsNestedWildcard3() { + return "Set. @TC GInner> entrySet() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + }) + public String methodReturnAsNestedWildcard4() { + return "Set. @TC GInner> entrySet() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + }) + public String methodReturnAsNestedWildcard5() { + return "Set entrySet() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 0 }), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0, 3, 1 }), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = { 3, 0, 2, 0, 1, 0 }), + }) + public String methodReturnAsNestedWildcard6() { + return "Set. @TC GInner<@TA String, @TB Object>> entrySet() { return null; }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java new file mode 100644 index 00000000000..457ca5b0a10 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method exception clauses + * @compile -g Driver.java ReferenceInfoUtil.java MethodThrows.java + * @run main Driver MethodThrows + */ +public class MethodThrows { + + @TADescriptions({ + @TADescription(annotation = "TA", type = THROWS, typeIndex = 0), + @TADescription(annotation = "TB", type = THROWS, typeIndex = 2) + }) + public String regularMethod() { + return "class Test { void test() throws @TA RuntimeException, IllegalArgumentException, @TB Exception { } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = THROWS, typeIndex = 0), + @TADescription(annotation = "TB", type = THROWS, typeIndex = 2) + }) + public String abstractMethod() { + return "abstract class Test { abstract void test() throws @TA RuntimeException, IllegalArgumentException, @TB Exception; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = THROWS, typeIndex = 0), + @TADescription(annotation = "TB", type = THROWS, typeIndex = 2) + }) + public String interfaceMethod() { + return "interface Test { void test() throws @TA RuntimeException, IllegalArgumentException, @TB Exception; }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java new file mode 100644 index 00000000000..5798eaa9b49 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for method type parameters + * @compile -g Driver.java ReferenceInfoUtil.java MethodTypeParam.java + * @run main Driver MethodTypeParam + */ +public class MethodTypeParam { + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularClass() { + return "<@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> void test() { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularClass2() { + return "<@TA K extends @TB Date, @TC V extends @TE Cloneable> void test() { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0) + }) + public String regularClassParameterized() { + return ", V extends @TF Object & @TC List<@TD List<@TE Object>>> void test() { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String abstractClass() { + return "abstract class Test { abstract <@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0) + }) + public String abstractClassParameterized() { + return "abstract class Test { abstract , V extends @TF Object & @TC List<@TD List<@TE Object>>> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}) + }) + public String abstractClassParameterized2() { + return "abstract class Test { abstract , V extends @TC List<@TD List<@TE Object>>> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String abstractClassParameterized3() { + return "abstract class Test { abstract , V extends @TB List> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER, paramIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1) + }) + public String regularInterface() { + return "interface Test { <@TA K extends @TB Date, @TC V extends @TD Object & @TE Cloneable> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 0), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TH", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_TYPE_PARAMETER, paramIndex = 1) + }) + public String regularInterfaceParameterized() { + return "interface Test { <@TH K extends @TG Object & @TA Map, @TI V extends @TF Object & @TC List<@TD List<@TE Object>>> void test(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1, genericLocation = {3, 1}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 1, boundIndex = 1, genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER, paramIndex = 1) + }) + public String regularInterfaceParameterized2() { + return "interface Test { <@TF K extends @TA Map, @TG V extends @TC List<@TD List<@TE Object>>> void test(); }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN) + public String useInReturn1() { + return "class Test { @TA T m() { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {3, 0}) + public String useInReturn2() { + return "class Test { Class<@TA T> m() { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TB", type = METHOD_RETURN) + }) + public String useInReturn3() { + return "class Test { @TB T m() { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, genericLocation = {3, 0}) + public String useInParam1() { + return "class Test { void m(Class<@TA T> p) { throw new RuntimeException(); } }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, genericLocation = {3, 0}) + public String useInParam2() { + return "class Test { void m(Class<@TA Object> p) { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, paramIndex = 0, boundIndex = 2), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + }) + public String useInParam3() { + return "interface IA {} " + + "interface IB {} " + + "interface IC {} " + + "class Test { & @TB IC> void m(@TC T p) { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 1, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 2, + genericLocation = {}), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0) + }) + public String useInParam4() { + return "class Test {" + + " interface IA {} " + + " interface IB {} " + + " interface IC {} " + + " & @TB IC> void m(@TC T p) { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {1, 0}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {1, 0, 3, 0}), + }) + public String useInParam5() { + return "class Test {" + + " interface IA {} " + + " class CB {} " + + " > void m(T p) { throw new RuntimeException(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER, + paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {}), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 0, + genericLocation = {1, 0, 3, 0}), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 1, + genericLocation = {}), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, + paramIndex = 0, boundIndex = 1, + genericLocation = {3, 0}) + }) + public String useInParam6() { + return "class Test {" + + " interface IA {} " + + " interface IB {} " + + " class CC {} " + + " interface ID {} " + + " <@TA T extends @TB Test.CC<@TC IA> & Test. @TD ID<@TE IA>> void m(T p) { throw new RuntimeException(); } }"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java new file mode 100644 index 00000000000..69694e453be --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 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 static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @bug 8006732 8006775 + * @ignore + * @summary Test population of reference info for multicatch exception parameters + * @author Werner Dietl + * @compile -g Driver.java ReferenceInfoUtil.java MultiCatch.java + * @run main Driver MultiCatch + */ +public class MultiCatch { + + @TADescriptions({ + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0), + @TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1) + }) + public String multiCatch1() { + return "void multiCatch1() { " + + "try { new Object(); } catch (@TA NullPointerException | @TB IndexOutOfBoundsException e) { e.toString(); } }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0), + @TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1), + @TADescription(annotation = "TC", type = EXCEPTION_PARAMETER, exceptionIndex = 2), + }) + public String multiCatch2() { + return "void multiCatch2() { " + + "try { new Object(); } catch (@TA NullPointerException | @TB IndexOutOfBoundsException | @TC IllegalArgumentException e) { e.toString(); } }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java new file mode 100644 index 00000000000..e98df7bd0c2 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java @@ -0,0 +1,834 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for nested types + * @compile -g Driver.java ReferenceInfoUtil.java NestedTypes.java + * @run main Driver NestedTypes + */ +public class NestedTypes { + + // method parameters + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testParam1() { + return "void test(@TA Outer.@TB Inner a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 1, 0}, paramIndex = 0) + }) + public String testParam1b() { + return "void test(List<@TA Outer.@TB Inner> a) { }"; + } + + // TODO: the tests that use @TA Map.Entry should fail, as + // Map cannot be annotated. + // We need some tests for the fully qualified name syntax. + /* + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {}, paramIndex = 0) + public String testParam1c() { + return "void test(java.util.@TA Map.Entry a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testParam1d() { + return "void test(java.util.@TA Map.@TB Entry a) { }"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0) + public String testParam1e() { + return "void test(List a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 1, 0}, paramIndex = 0) + }) + public String testParam1f() { + return "void test(List a) { }"; + } + */ + + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0) + public String testParam1g() { + return "void test(List a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {1, 0}, paramIndex = 0) + }) + public String testParam2() { + return "void test(@TA GOuter.@TB GInner a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 1, 0}, paramIndex = 0) + }) + public String testParam2b() { + return "void test(List<@TA GOuter.@TB GInner> a) { }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, paramIndex = 0), + @TADescription(annotation = "TJ", type = METHOD_FORMAL_PARAMETER, paramIndex = 0), + @TADescription(annotation = "TK", type = METHOD_FORMAL_PARAMETER, + genericLocation = {0, 0}, paramIndex = 0) + }) + public String testParam3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " void test(@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[] a) { }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TD", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, paramIndex = 0), + @TADescription(annotation = "TG", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}, paramIndex = 0), + @TADescription(annotation = "TH", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, paramIndex = 0), + @TADescription(annotation = "TI", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, paramIndex = 0), + @TADescription(annotation = "TJ", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0}, paramIndex = 0), + @TADescription(annotation = "TK", type = METHOD_FORMAL_PARAMETER, + genericLocation = {3, 0, 0, 0}, paramIndex = 0) + }) + public String testParam4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " void test(List<@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]> a) { }\n" + + "}"; + } + + + // Local variables + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + }) + public String testLocal1a() { + return "void test() { @TA Outer.@TB Inner a = null; }"; + } + + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + public String testLocal1b() { + return "void test() { @TA Outer.Inner a = null; }"; + } + + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + public String testLocal1c() { + return "void test() { Outer.@TB Inner a = null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + }) + public String testLocal2() { + return "void test() { @TA GOuter.@TB GInner a = null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TC", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TD", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TE", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TF", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TG", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TH", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TI", type = LOCAL_VARIABLE, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TJ", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TK", type = LOCAL_VARIABLE, + genericLocation = {0, 0}, + lvarOffset = {5}, lvarLength = {1}, lvarIndex = {1}) + }) + public String testLocal3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " void test() { @TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[] a = null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TC", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TD", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TE", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TF", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TG", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TH", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TI", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TJ", type = LOCAL_VARIABLE, + genericLocation = {3, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}), + @TADescription(annotation = "TK", type = LOCAL_VARIABLE, + genericLocation = {3, 0, 0, 0}, + lvarOffset = {2}, lvarLength = {1}, lvarIndex = {1}) + }) + public String testLocal4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " void test() { List<@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]> a = null; }\n" + + "}"; + } + + + // fields + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {1, 0}) + }) + public String testField1a() { + return "@TA Outer.@TB Inner a;"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {}) + public String testField1b() { + return "@TA Outer.Inner a;"; + } + + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {1, 0}) + public String testField1c() { + return "Outer.@TB Inner a;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {1, 0}) + }) + public String testField2() { + return "@TA GOuter.@TB GInner a;"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {0, 0, 0, 0}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0}), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TE", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TF", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TG", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}), + @TADescription(annotation = "TH", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TI", type = FIELD, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 1}), + @TADescription(annotation = "TJ", type = FIELD), + @TADescription(annotation = "TK", type = FIELD, + genericLocation = {0, 0}) + }) + public String testField3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " @TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[] a;\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}), + @TADescription(annotation = "TC", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TD", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TE", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TF", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TG", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}), + @TADescription(annotation = "TH", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TI", type = FIELD, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}), + @TADescription(annotation = "TJ", type = FIELD, + genericLocation = {3, 0}), + @TADescription(annotation = "TK", type = FIELD, + genericLocation = {3, 0, 0, 0}) + }) + public String testField4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " List<@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]> a;\n" + + "}"; + } + + + // return types + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {1, 0}) + }) + public String testReturn1() { + return "@TA Outer.@TB Inner test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {1, 0}) + }) + public String testReturn2() { + return "@TA GOuter.@TB GInner test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0}), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TE", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TG", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}), + @TADescription(annotation = "TH", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TI", type = METHOD_RETURN, + genericLocation = {0, 0, 0, 0, 1, 0, 1, 0, 3, 1}), + @TADescription(annotation = "TJ", type = METHOD_RETURN), + @TADescription(annotation = "TK", type = METHOD_RETURN, + genericLocation = {0, 0}) + }) + public String testReturn3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " @TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[] test() { return null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TE", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TF", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TG", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}), + @TADescription(annotation = "TH", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TI", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}), + @TADescription(annotation = "TJ", type = METHOD_RETURN, + genericLocation = {3, 0}), + @TADescription(annotation = "TK", type = METHOD_RETURN, + genericLocation = {3, 0, 0, 0}) + }) + public String testReturn4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " List<@TA Outer . @TB GInner<@TC List<@TD Object @TE[] @TF[]>>. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]> test() { return null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_RETURN, + genericLocation = {3, 0}), + @TADescription(annotation = "TB", type = METHOD_RETURN, + genericLocation = {3, 0, 3, 0}), + @TADescription(annotation = "TC", type = METHOD_RETURN, + genericLocation = {3, 0, 3, 1}), + @TADescription(annotation = "TD", type = METHOD_RETURN, + genericLocation = {3, 0, 3, 1, 3, 0}), + @TADescription(annotation = "TE", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0}), + @TADescription(annotation = "TF", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 3, 0}), + @TADescription(annotation = "TG", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}), + @TADescription(annotation = "TH", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0}), + @TADescription(annotation = "TI", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0, 0, 0}), + @TADescription(annotation = "TJ", type = METHOD_RETURN, + genericLocation = {3, 0, 1, 0, 1, 0}), + }) + public String testReturn5() { + return "class GOuter {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " List<@TA GOuter<@TB String, @TC List<@TD Object>> . @TE GInner<@TF List<@TG Object @TH[] @TI[]>>. @TJ GInner2> test() { return null; }\n" + + "}"; + } + + + // type parameters + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {}, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0}, paramIndex = 0, boundIndex = 0) + }) + public String testTypeparam1() { + return " X test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {}, paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0}, paramIndex = 0, boundIndex = 0) + }) + public String testTypeparam2() { + return ".@TB GInner> X test() { return null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 3, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 3, 0, 3, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 3, 0, 3, 0, 0, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 1, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TH", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 1, 0, 3, 0}, + paramIndex = 0, boundIndex = 0), + @TADescription(annotation = "TI", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {1, 0, 1, 0, 3, 1}, + paramIndex = 0, boundIndex = 0), + }) + public String testTypeparam3() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " >. @TG GInner2<@TH Integer, @TI Object>> X test() { return null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 3, 0, 0, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TH", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TI", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 3, 1}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TJ", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0}, + paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TK", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 0, 0}, + paramIndex = 0, boundIndex = 1) + }) + public String testTypeparam4() { + return "class Outer {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " >. @TG GInner2<@TH Integer, @TI Object> @TJ[] @TK[]>> X test() { return null; }\n" + + "}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TB", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TC", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 3, 1}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TD", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 3, 1, 3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TE", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TF", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TG", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TH", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TI", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 3, 0, 3, 0, 0, 0}, paramIndex = 0, boundIndex = 1), + @TADescription(annotation = "TJ", type = METHOD_TYPE_PARAMETER_BOUND, + genericLocation = {3, 0, 1, 0, 1, 0}, paramIndex = 0, boundIndex = 1), + }) + public String testTypeparam5() { + return "class GOuter {\n" + + " class GInner {\n" + + " class GInner2 {}\n" + + "}}\n\n" + + "class Test {\n" + + " > . @TE GInner<@TF List<@TG Object @TH[] @TI[]>>. @TJ GInner2>> X test() { return null; }\n" + + "}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0}) + public String testUses1a() { + return "class Test { class Inner {} List<@TA Inner> f; }"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0}) + public String testUses1b() { + return "class Test { class Inner {} List<@TA Test.Inner> f; }"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2a() { + return "class Test { class Inner { class Inner2{} List<@TA Inner2> f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2b() { + return "class Test { class Inner { class Inner2{} List<@TA Inner.Inner2> f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2c() { + return "class Test { class Inner { class Inner2{} List f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0}) + @TestClass("Test$Inner") + public String testUses2d() { + return "class Test{ class Inner { class Inner2{} List<@TA Test.Inner.Inner2> f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2e() { + return "class Test { class Inner { class Inner2{} List f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses2f() { + return "class Test { class Inner { class Inner2{} List f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses3a() { + return "class Test { class Inner { class Inner2{}\n" + + " List f; }}"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0}) + @TestClass("Test$Inner") + public String testUses3b() { + return "class Test { class Inner { class Inner2{}\n" + + " List f; }}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {}), + @TADescription(annotation = "TB", type = FIELD, + genericLocation = {3, 0}) + }) + public String testUses4() { + return "class Test { static class TInner {}\n" + + " @TA TInner f; \n" + + " List<@TB TInner> g; }"; + } + + @TADescription(annotation = "TA", type = FIELD, + genericLocation = {3, 0, 1, 0, 3, 1}) + @TestClass("Test$Inner") + public String testUses3c() { + return "class Test { class Inner { class Inner2{}\n" + + " List.Inner2> f; }}"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex=0) + public String testFullyQualified1() { + return "void testme(java.security.@TA ProtectionDomain protectionDomain) {}"; + } + + @TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex=0, + genericLocation = {3, 0}) + public String testFullyQualified2() { + return "void testme(List protectionDomain) {}"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = LOCAL_VARIABLE, + genericLocation = {}, + lvarOffset = ReferenceInfoUtil.IGNORE_VALUE, + lvarLength = ReferenceInfoUtil.IGNORE_VALUE, + lvarIndex = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = LOCAL_VARIABLE, + genericLocation = {1, 0}, + lvarOffset = ReferenceInfoUtil.IGNORE_VALUE, + lvarLength = ReferenceInfoUtil.IGNORE_VALUE, + lvarIndex = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = LOCAL_VARIABLE, + // Only classes count, not methods. + genericLocation = {1, 0, 1, 0}, + lvarOffset = ReferenceInfoUtil.IGNORE_VALUE, + lvarLength = ReferenceInfoUtil.IGNORE_VALUE, + lvarIndex = ReferenceInfoUtil.IGNORE_VALUE), + }) + @TestClass("Outer$Inner") + public String testMethodNesting1() { + return "class Outer {\n" + + " class Inner {\n" + + " void foo() {\n" + + " class MInner {}\n" + + " @TA Outer . @TB Inner l1 = null;\n" + + " @TC MInner l2 = null;\n" + + " }\n" + + "}}\n"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = NEW, + genericLocation = {}, + offset = 0), + @TADescription(annotation = "TB", type = NEW, + genericLocation = {1, 0}, + offset = 0), + @TADescription(annotation = "TC", type = NEW, + // Only classes count, not methods. + genericLocation = {1, 0, 1, 0}, + offset = 12), + }) + @TestClass("Outer$Inner") + public String testMethodNesting2() { + return "class Outer {\n" + + " class Inner {\n" + + " void foo() {\n" + + " class MInner {}\n" + + " Object o1 = new @TA Outer . @TB Inner();" + + " Object o2 = new @TC MInner();\n" + + " }\n" + + "}}\n"; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java new file mode 100644 index 00000000000..fb3e3f55eeb --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for new object creations + * @compile -g Driver.java ReferenceInfoUtil.java NewObjects.java + * @run main Driver NewObjects + */ +public class NewObjects { + + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String returnObject() { + return "Object returnObject() { return new @TA String(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = NEW, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnObjectGeneric() { + return "Object returnObjectGeneric() { return new @TA ArrayList<@TB String>(); }"; + } + + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String initObject() { + return "void initObject() { Object a = new @TA String(); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = NEW, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = NEW, + genericLocation = { 3, 1 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initObjectGeneric() { + return "void initObjectGeneric() { Object a = new @TA HashMap<@TB String, @TC String>(); }"; + } + + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String eqtestObject() { + return "void eqtestObject() { if (null == new @TA String()); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = NEW, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestObjectGeneric() { + return "void eqtestObjectGeneric() { if (null == new @TA ArrayList<@TB String >()); }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java new file mode 100644 index 00000000000..33ae4edaabf --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.TypeAnnotation; +import com.sun.tools.classfile.Field; +import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute; +import com.sun.tools.classfile.ConstantPool.InvalidIndex; +import com.sun.tools.classfile.ConstantPool.UnexpectedEntry; + +public class ReferenceInfoUtil { + + public static final int IGNORE_VALUE = -321; + + public static List extendedAnnotationsOf(ClassFile cf) { + List annos = new ArrayList(); + findAnnotations(cf, annos); + return annos; + } + + /////////////////// Extract type annotations ////////////////// + private static void findAnnotations(ClassFile cf, List annos) { + findAnnotations(cf, Attribute.RuntimeVisibleTypeAnnotations, annos); + findAnnotations(cf, Attribute.RuntimeInvisibleTypeAnnotations, annos); + + for (Field f : cf.fields) { + findAnnotations(cf, f, annos); + } + for (Method m: cf.methods) { + findAnnotations(cf, m, annos); + } + } + + private static void findAnnotations(ClassFile cf, Method m, List annos) { + findAnnotations(cf, m, Attribute.RuntimeVisibleTypeAnnotations, annos); + findAnnotations(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, annos); + } + + private static void findAnnotations(ClassFile cf, Field m, List annos) { + findAnnotations(cf, m, Attribute.RuntimeVisibleTypeAnnotations, annos); + findAnnotations(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, annos); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + private static void findAnnotations(ClassFile cf, String name, List annos) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + annos.addAll(Arrays.asList(tAttr.annotations)); + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + private static void findAnnotations(ClassFile cf, Method m, String name, List annos) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + annos.addAll(Arrays.asList(tAttr.annotations)); + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + private static void findAnnotations(ClassFile cf, Field m, String name, List annos) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + annos.addAll(Arrays.asList(tAttr.annotations)); + } + } + + /////////////////// TA Position Builder /////////////////////// + /* TODO: comment out this dead code. Was this unfinished code that was + * supposed to be used somewhere? The tests pass without this. + private static class TAPositionBuilder { + private TypeAnnotation.Position pos = new TypeAnnotation.Position(); + + private TAPositionBuilder() { } + + public TypeAnnotation.Position build() { return pos; } + + public static TAPositionBuilder ofType(TypeAnnotation.TargetType type) { + TAPositionBuilder builder = new TAPositionBuilder(); + builder.pos.type = type; + return builder; + } + + public TAPositionBuilder atOffset(int offset) { + switch (pos.type) { + // type cast + case TYPECAST: + // instanceof + case INSTANCEOF: + // new expression + case NEW: + pos.offset = offset; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atLocalPosition(int offset, int length, int index) { + switch (pos.type) { + // local variable + case LOCAL_VARIABLE: + pos.lvarOffset = new int[] { offset }; + pos.lvarLength = new int[] { length }; + pos.lvarIndex = new int[] { index }; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atParameterIndex(int index) { + switch (pos.type) { + // type parameters + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: + // method parameter + case METHOD_FORMAL_PARAMETER: + pos.parameter_index = index; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atParamBound(int param, int bound) { + switch (pos.type) { + // type parameters bounds + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + pos.parameter_index = param; + pos.bound_index = bound; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atWildcardPosition(TypeAnnotation.Position pos) { + switch (pos.type) { + // wildcards + case WILDCARD_BOUND: + pos.wildcard_position = pos; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atTypeIndex(int index) { + switch (pos.type) { + // class extends or implements clauses + case CLASS_EXTENDS: + // throws + case THROWS: + pos.type_index = index; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atOffsetWithIndex(int offset, int index) { + switch (pos.type) { + // method type argument: wasn't specified + case NEW_TYPE_ARGUMENT: + case METHOD_TYPE_ARGUMENT: + pos.offset = offset; + pos.type_index = index; + break; + default: + throw new IllegalArgumentException("invalid field for given type: " + pos.type); + } + return this; + } + + public TAPositionBuilder atGenericLocation(Integer ...loc) { + pos.location = Arrays.asList(loc); + pos.type = pos.type.getGenericComplement(); + return this; + } + }*/ + + /////////////////////// Equality testing ///////////////////// + private static boolean areEquals(int a, int b) { + return a == b || a == IGNORE_VALUE || b == IGNORE_VALUE; + } + + private static boolean areEquals(int[] a, int[] a2) { + if (a==a2) + return true; + if (a==null || a2==null) + return false; + + int length = a.length; + if (a2.length != length) + return false; + + for (int i=0; i annotations, ClassFile cf) throws InvalidIndex, UnexpectedEntry { + String properName = "L" + name + ";"; + for (TypeAnnotation anno : annotations) { + String actualName = cf.constant_pool.getUTF8Value(anno.annotation.type_index); + if (properName.equals(actualName)) + return anno; + } + return null; + } + + public static boolean compare(Map expectedAnnos, + List actualAnnos, ClassFile cf) throws InvalidIndex, UnexpectedEntry { + if (actualAnnos.size() != expectedAnnos.size()) { + throw new ComparisionException("Wrong number of annotations", + expectedAnnos, + actualAnnos); + } + + for (Map.Entry e : expectedAnnos.entrySet()) { + String aName = e.getKey(); + TypeAnnotation.Position expected = e.getValue(); + TypeAnnotation actual = findAnnotation(aName, actualAnnos, cf); + if (actual == null) + throw new ComparisionException("Expected annotation not found: " + aName); + + // TODO: you currently get an exception if the test case does not use all necessary + // annotation attributes, e.g. forgetting the offset for a local variable. + // It would be nicer to give an understandable warning instead. + if (!areEquals(expected, actual.position)) { + throw new ComparisionException("Unexpected position for annotation : " + aName + + "\n Expected: " + expected.toString() + + "\n Found: " + actual.position.toString()); + } + } + return true; + } +} + +class ComparisionException extends RuntimeException { + private static final long serialVersionUID = -3930499712333815821L; + + public final Map expected; + public final List found; + + public ComparisionException(String message) { + this(message, null, null); + } + + public ComparisionException(String message, Map expected, List found) { + super(message); + this.expected = expected; + this.found = found; + } + + public String toString() { + String str = super.toString(); + if (expected != null && found != null) { + str += "\n\tExpected: " + expected.size() + " annotations; but found: " + found.size() + " annotations\n" + + " Expected: " + expected + + "\n Found: " + found; + } + return str; + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java new file mode 100644 index 00000000000..22982ae4d27 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for repeating type annotations + * @compile -g Driver.java ReferenceInfoUtil.java RepeatingTypeAnnotations.java + * @run main Driver RepeatingTypeAnnotations + * @author Werner Dietl + */ +public class RepeatingTypeAnnotations { + // Field types + @TADescription(annotation = "RTAs", type = FIELD) + public String fieldAsPrimitive() { + return "@RTA @RTA int test;"; + } + + // Method returns + @TADescription(annotation = "RTAs", type = METHOD_RETURN) + public String methodReturn1() { + return "@RTA @RTA int test() { return 0; }"; + } + + @TADescription(annotation = "RTAs", type = METHOD_RETURN) + public String methodReturn2() { + return "@RTAs({@RTA, @RTA}) int test() { return 0; }"; + } + + // Method parameters + @TADescriptions({ + @TADescription(annotation = "RTAs", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0), + @TADescription(annotation = "RTBs", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, + genericLocation = { 3, 0 }) + }) + public String methodParam1() { + return "void m(@RTA @RTA List<@RTB @RTB String> p) {}"; + } + + @TADescriptions({ + @TADescription(annotation = "RTAs", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0), + @TADescription(annotation = "RTBs", type = METHOD_FORMAL_PARAMETER, + paramIndex = 0, + genericLocation = { 3, 0 }) + }) + public String methodParam2() { + return "void m(@RTAs({@RTA, @RTA}) List<@RTBs({@RTB, @RTB}) String> p) {}"; + } + + // TODO: test that all other locations work with repeated type annotations. +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java new file mode 100644 index 00000000000..84e5e01b358 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for type casts + * @compile -g Driver.java ReferenceInfoUtil.java TypeCasts.java + * @run main Driver TypeCasts + */ +public class TypeCasts { + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String returnObject() { + return "Object returnObject() { return (@TA String)null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = CAST, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnObjectArray() { + return "Object returnObjectArray() { return (@TC String @TA [] @TB [])null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnObjectGeneric() { + return "Object returnObjectGeneric() { return (@TA List<@TB String>)null; }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String returnPrim() { + return "Object returnPrim() { return (@TA int)0; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnPrimArray() { + return "Object returnPrimArray() { return (@TB int @TA [])null; }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String initObject() { + return "void initObject() { Object a = (@TA String)null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initObjectArray() { + return "void initObjectArray() { Object a = (@TB String @TA [])null; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initObjectGeneric() { + return "void initObjectGeneric() { Object a = (@TA List<@TB String>)null; }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String initPrim() { + return "void initPrim() { Object a = (@TA int)0; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initPrimArray() { + return "void initPrimArray() { Object a = (@TB int @TA [])null; }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String eqtestObject() { + return "void eqtestObject() { if (null == (@TA String)null); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestObjectArray() { + return "void eqtestObjectArray() { if (null == (@TB String @TA [])null); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestObjectGeneric() { + return "void eqtestObjectGeneric() { if (null == (@TA List<@TB String >)null); }"; + } + + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE) + // compiler optimizes away compile time constants casts + public String eqtestPrim() { + return "void eqtestPrim(int a) { if (0 == (@TA int)a); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = CAST, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestPrimArray() { + return "void eqtestPrimArray() { if (null == (@TB int @TA [])null); }"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java new file mode 100644 index 00000000000..3b319197afe --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 com.sun.tools.classfile.TypeAnnotation.TargetType.*; + +/* + * @test + * @summary Test population of reference info for class literals + * @compile -g Driver.java ReferenceInfoUtil.java TypeTests.java + * @run main Driver TypeTests + */ +public class TypeTests { + + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String returnObject() { + return "Object returnObject() { return null instanceof @TA String; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnObjectArray() { + return "Object returnObjectArray() { return null instanceof @TC String @TA [] @TB []; }"; + } + + // no type test for primitives + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String returnPrimArray() { + return "Object returnPrimArray() { return null instanceof @TC int @TA [] @TB []; }"; + } + + // no void + // no void array + + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String initObject() { + return "void initObject() { Object a = null instanceof @TA String; }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initObjectArray() { + return "void initObjectArray() { Object a = null instanceof @TC String @TA [] @TB []; }"; + } + + // no primitive instanceof + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String initPrimArray() { + return "void initPrimArray() { Object a = null instanceof @TC int @TA [] @TB []; }"; + } + + // no void + // no void array + + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE) + public String eqtestObject() { + return "void eqtestObject() { if (true == (null instanceof @TA String)); }"; + } + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestObjectArray() { + return "void eqtestObjectArray() { if (true == (null instanceof @TC String @TA [] @TB [])); }"; + } + + // no primitives + + @TADescriptions({ + @TADescription(annotation = "TA", type = INSTANCEOF, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TB", type = INSTANCEOF, + genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE), + @TADescription(annotation = "TC", type = INSTANCEOF, + genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE) + }) + public String eqtestPrimArray() { + return "void eqtestPrimArray() { if (true == (null instanceof @TC int @TA [] @TB [])); }"; + } + + // no void + // no void array + +} diff --git a/langtools/test/tools/javac/api/8007344/Test.java b/langtools/test/tools/javac/api/8007344/Test.java new file mode 100644 index 00000000000..871faa70617 --- /dev/null +++ b/langtools/test/tools/javac/api/8007344/Test.java @@ -0,0 +1,227 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8007344 + * @summary javac may not make tree end positions and/or doc comments + * available to processors and listeners + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor + * @run main Test + */ + +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Set; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.doctree.DocCommentTree; +import com.sun.source.tree.*; +import com.sun.source.util.DocTrees; +import com.sun.source.util.JavacTask; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePath; +import com.sun.source.util.TreePathScanner; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.Pretty; +import com.sun.tools.javac.util.Position; + +/** Doc comment: Test */ +public class Test { + public static final int EXPECT_DOC_COMMENTS = 3; + + /** Doc comment: main */ + public static void main(String... args) throws Exception { + PrintWriter out = new PrintWriter(System.err); + try { + new Test(out).run(); + } finally { + out.flush(); + } + } + + PrintWriter out; + int errors; + + Test(PrintWriter out) { + this.out = out; + } + + /** Doc comment: run */ + void run() throws Exception { + File testSrc = new File(System.getProperty("test.src")); + File thisFile = new File(testSrc, getClass().getName() + ".java"); + JavacTool javac = JavacTool.create(); + StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null); + Iterable fos = fm.getJavaFileObjects(thisFile); + testAnnoProcessor(javac, fm, fos, out, EXPECT_DOC_COMMENTS); + testTaskListener(javac, fm, fos, out, EXPECT_DOC_COMMENTS); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void testAnnoProcessor(JavacTool javac, StandardJavaFileManager fm, + Iterable files, PrintWriter out, + int expectedDocComments) { + out.println("Test annotation processor"); + JavacTask task = javac.getTask(out, fm, null, null, null, files); + AnnoProc ap = new AnnoProc(DocTrees.instance(task)); + task.setProcessors(Arrays.asList(ap)); + task.call(); + ap.checker.checkDocComments(expectedDocComments); + } + + void testTaskListener(JavacTool javac, StandardJavaFileManager fm, + Iterable files, PrintWriter out, + int expectedDocComments) { + out.println("Test task listener"); + JavacTask task = javac.getTask(out, fm, null, null, null, files); + TaskListnr tl = new TaskListnr(DocTrees.instance(task)); + task.addTaskListener(tl); + task.call(); + tl.checker.checkDocComments(expectedDocComments); + } + + void error(String msg) { + out.println("Error: " + msg); + errors++; + } + + class AnnoProc extends JavacTestingAbstractProcessor { + Checker checker; + + AnnoProc(DocTrees trees) { + checker = new Checker(trees); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (Element e : roundEnv.getRootElements()) { + checker.scan(checker.trees.getPath(e), null); + } + return true; + } + } + + class TaskListnr implements TaskListener { + Checker checker; + + TaskListnr(DocTrees trees) { + checker = new Checker(trees); + } + + public void started(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.ANALYZE) + checker.scan(new TreePath(e.getCompilationUnit()), null); + } + + public void finished(TaskEvent e) { + } + } + + class Checker extends TreePathScanner { + DocTrees trees; + SourcePositions srcPosns; + + int docComments = 0; + + Checker(DocTrees trees) { + this.trees = trees; + srcPosns = trees.getSourcePositions(); + } + + @Override + public Void scan(Tree tree, Void ignore) { + if (tree != null) { + switch (tree.getKind()) { + // HACK: Workaround 8007350 + // Some tree nodes do not have endpos set + case ASSIGNMENT: + case BLOCK: + case IDENTIFIER: + case METHOD_INVOCATION: + break; + + default: + checkEndPos(getCurrentPath().getCompilationUnit(), tree); + } + } + return super.scan(tree, ignore); + } + + @Override + public Void visitClass(ClassTree tree, Void ignore) { + checkComment(); + return super.visitClass(tree, ignore); + } + + @Override + public Void visitMethod(MethodTree tree, Void ignore) { + checkComment(); + return super.visitMethod(tree, ignore); + } + + @Override + public Void visitVariable(VariableTree tree, Void ignore) { + checkComment(); + return super.visitVariable(tree, ignore); + } + + void checkComment() { + DocCommentTree dc = trees.getDocCommentTree(getCurrentPath()); + if (dc != null) { + out.println("comment: " + dc.toString().replaceAll("\\s+", " ")); + docComments++; + } + } + + void checkEndPos(CompilationUnitTree unit, Tree tree) { + long sp = srcPosns.getStartPosition(unit, tree); + long ep = srcPosns.getEndPosition(unit, tree); + if (sp >= 0 && ep == Position.NOPOS) { + error("endpos not set for " + tree.getKind() + + " " + Pretty.toSimpleString(((JCTree) tree)) + +", start:" + sp); + } + } + + void checkDocComments(int expected) { + if (docComments != expected) { + error("Unexpected number of doc comments received: " + + docComments + ", expected: " + expected); + } + } + + } +} diff --git a/langtools/test/tools/javac/api/EndPositions.java b/langtools/test/tools/javac/api/EndPositions.java index 1971a7dd5ac..f791cc7666b 100644 --- a/langtools/test/tools/javac/api/EndPositions.java +++ b/langtools/test/tools/javac/api/EndPositions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -28,11 +28,7 @@ * an annotation processor is present */ -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.Tree; import com.sun.source.util.JavacTask; -import com.sun.source.util.Trees; import java.io.IOException; import java.net.URI; import java.util.Arrays; @@ -72,16 +68,17 @@ public class EndPositions extends AbstractProcessor { JavacTask task = (JavacTask)javac.getTask(null, null, diagnostics, options, null, compilationUnits); boolean valid = task.call(); if (valid) - throw new AssertionError("Compilation succeeded unexpectedly"); + throw new AssertionError("Expected one error, but found none."); List> errors = diagnostics.getDiagnostics(); if (errors.size() != 1) - throw new AssertionError("Expected one error only, but found " + errors.size() + " errors"); + throw new AssertionError("Expected one error only, but found " + errors.size() + "; errors: " + errors); Diagnostic error = errors.get(0); if (error.getStartPosition() >= error.getEndPosition()) throw new AssertionError("Expected start to be less than end position: start [" + - error.getStartPosition() + "], end [" + error.getEndPosition() +"]"); + error.getStartPosition() + "], end [" + error.getEndPosition() +"]" + + "; diagnostics code: " + error.getCode()); System.out.println("All is good!"); } diff --git a/langtools/test/tools/javac/api/T6306137.java b/langtools/test/tools/javac/api/T6306137.java index b961d800e4b..8ccf577b088 100644 --- a/langtools/test/tools/javac/api/T6306137.java +++ b/langtools/test/tools/javac/api/T6306137.java @@ -26,9 +26,6 @@ * @bug 6306137 * @summary JSR 199: encoding option doesn't affect standard file manager * @author Peter von der Ahé - * @ignore - * Need to make the contentCache in JavacFileManager be aware of changes to the encoding. - * Need to propogate -source (and -encoding?) down to the JavacFileManager */ import java.io.File; diff --git a/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java index 262ef48e03f..7aea2d42476 100644 --- a/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java +++ b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java @@ -23,13 +23,17 @@ /* * @test - * @bug 8002099 + * @bug 8002099 8006694 * @summary Add support for intersection types in cast expression + * temporarily workaround combo tests are causing time out in several platforms * @library ../../lib * @build JavacTestingAbstractThreadedTest - * @run main/timeout=360 IntersectionTypeCastTest + * @run main/othervm/timeout=360 IntersectionTypeCastTest */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import javax.tools.Diagnostic; @@ -287,8 +291,7 @@ public class IntersectionTypeCastTest final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker, - Arrays.asList("-XDallowIntersectionTypes"), - null, Arrays.asList(source)); + null, null, Arrays.asList(source)); try { ct.analyze(); } catch (Throwable ex) { diff --git a/langtools/test/tools/javac/cast/intersection/IntersectionTypeParserTest.java b/langtools/test/tools/javac/cast/intersection/IntersectionTypeParserTest.java index 7f113900bc6..c699bab9e69 100644 --- a/langtools/test/tools/javac/cast/intersection/IntersectionTypeParserTest.java +++ b/langtools/test/tools/javac/cast/intersection/IntersectionTypeParserTest.java @@ -170,7 +170,7 @@ public class IntersectionTypeParserTest { void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { checkCount++; JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, - Arrays.asList("-XDallowIntersectionTypes"), null, Arrays.asList(source)); + null, null, Arrays.asList(source)); ct.parse(); if (diagChecker.errorFound) { throw new Error("Unexpected parser error for source:\n" + diff --git a/langtools/test/tools/javac/cast/intersection/model/Model01.java b/langtools/test/tools/javac/cast/intersection/model/Model01.java index 4bcd0c243c2..21740179f49 100644 --- a/langtools/test/tools/javac/cast/intersection/model/Model01.java +++ b/langtools/test/tools/javac/cast/intersection/model/Model01.java @@ -27,7 +27,7 @@ * @summary Add support for intersection types in cast expression * @library /tools/javac/lib * @build JavacTestingAbstractProcessor ModelChecker - * @compile -XDallowIntersectionTypes -processor ModelChecker Model01.java + * @compile -processor ModelChecker Model01.java */ import javax.lang.model.element.ElementKind; diff --git a/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java index a52cfb7240e..328629c51e7 100644 --- a/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java +++ b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java @@ -23,7 +23,6 @@ /* * @test - * @ignore awaits for VM support * @summary check that javac does not generate bridge methods for defaults */ diff --git a/langtools/test/tools/javac/defaultMethods/static/Static01.java b/langtools/test/tools/javac/defaultMethods/static/Static01.java new file mode 100644 index 00000000000..d1e1b3ab092 --- /dev/null +++ b/langtools/test/tools/javac/defaultMethods/static/Static01.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8005166 + * @summary Add support for static interface methods + * smoke test for static interface methods + * @compile -XDallowStaticInterfaceMethods Static01.java + */ +public class Static01 { + + static int assertionCount = 0; + + static void assertTrue(boolean cond) { + assertionCount++; + if (!cond) + throw new AssertionError(); + } + + interface I { + public static void test() { + assertTrue(true); + } + } + + public static void main(String[] args) { + I.test(); + assertTrue(assertionCount == 1); + } +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java b/langtools/test/tools/javac/defaultMethods/static/Static02.java similarity index 71% rename from langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java rename to langtools/test/tools/javac/defaultMethods/static/Static02.java index a8a8a633d6b..e539e58345c 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java +++ b/langtools/test/tools/javac/defaultMethods/static/Static02.java @@ -21,22 +21,22 @@ * questions. */ -/** +/* * @test - * @summary Smoke test for repeating annotations - * @compile/fail UseWrongContainedBy.java - * @bug 7151010 + * @bug 8005166 + * @summary Add support for static interface methods + * smoke test for static interface methods + * @compile/fail/ref=Static02.out -XDrawDiagnostics -XDallowStaticInterfaceMethods Static02.java */ +class Static02 { -import java.lang.annotation.*; + interface I { + public static void test() { } + } -@ContainerFor(UseWrongContainedBy.class) -@interface Foos { - UseWrongContainedBy[] value(); + public static void main(String[] args) { + I.test(); //ok + I i = new I() {}; + i.test(); //no! + } } - -@ContainedBy(Target.class) -public @interface UseWrongContainedBy {} - -@UseWrongContainedBy @UseWrongContainedBy -@interface Foo {} diff --git a/langtools/test/tools/javac/defaultMethods/static/Static02.out b/langtools/test/tools/javac/defaultMethods/static/Static02.out new file mode 100644 index 00000000000..10a5722a856 --- /dev/null +++ b/langtools/test/tools/javac/defaultMethods/static/Static02.out @@ -0,0 +1,2 @@ +Static02.java:40:15: compiler.err.illegal.static.intf.meth.call: Static02.I +1 error diff --git a/langtools/test/tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java b/langtools/test/tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java new file mode 100644 index 00000000000..6a14608ccf8 --- /dev/null +++ b/langtools/test/tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8005166 + * @summary Add support for static interface methods + * Smoke test for static interface method hiding + */ + +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; + + +public class InterfaceMethodHidingTest { + + static int checkCount = 0; + + 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;"); + + String sigStr; + String retStr; + + SignatureKind(String sigStr, String retStr) { + this.sigStr = sigStr; + this.retStr = retStr; + } + + boolean overrideEquivalentWith(SignatureKind s2) { + switch (this) { + case VOID_INTEGER: + case STRING_INTEGER: + return s2 == VOID_INTEGER || s2 == STRING_INTEGER; + case VOID_STRING: + case STRING_STRING: + return s2 == VOID_STRING || s2 == STRING_STRING; + default: + throw new AssertionError("bad signature kind"); + } + } + } + + enum MethodKind { + VIRTUAL("", "#M #S;"), + STATIC("static", "#M #S { #BE; #R }"), + DEFAULT("default", "#M #S { #BE; #R }"); + + String modStr; + String methTemplate; + + MethodKind(String modStr, String methTemplate) { + this.modStr = modStr; + this.methTemplate = methTemplate; + } + + boolean inherithed() { + return this != STATIC; + } + + static boolean overrides(MethodKind mk1, SignatureKind sk1, MethodKind mk2, SignatureKind sk2) { + return sk1 == sk2 && + mk2.inherithed() && + 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); + } + } + + enum BodyExpr { + NONE(""), + THIS("Object o = this"); + + String bodyExprStr; + + BodyExpr(String bodyExprStr) { + this.bodyExprStr = bodyExprStr; + } + + boolean allowed(MethodKind mk) { + return this == NONE || + mk != MethodKind.STATIC; + } + } + + public static void main(String... args) throws Exception { + + //create default shared JavaCompiler - reused across multiple compilations + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + 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); + } + + MethodKind mk1, mk2, mk3; + SignatureKind sk1, sk2, sk3; + BodyExpr be1, be2, be3; + JavaSource source; + DiagnosticChecker diagChecker; + + 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" + + " default void sup() { }\n" + + "}\n" + + "interface A extends Sup {\n" + + " #M1\n" + + "}\n" + + "interface B extends A, Sup {\n" + + " #M2\n" + + "}\n" + + "interface C extends B, Sup {\n" + + " #M3\n" + + "}\n"; + + String source; + + 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; + } + } + + 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() { + 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 (mk2.inherithed()) { + errorExpected |= + sk3.overrideEquivalentWith(sk2) && !MethodKind.overrides(mk3, sk3, mk2, sk2); + } + + 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 { + + boolean errorFound; + + public void report(Diagnostic diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + errorFound = true; + } + } + } +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport1.java similarity index 78% rename from langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java rename to langtools/test/tools/javac/defaultMethods/static/import/StaticImport1.java index 7d22aebf9b3..e976a32fff5 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java +++ b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport1.java @@ -21,18 +21,18 @@ * questions. */ -/** +/* * @test - * @summary Smoke test for repeating annotations - * @compile/fail MissingContainerFor.java - * @bug 7151010 + * @bug 8005166 + * @summary Add support for static interface methods + * Smoke test for static imports of static interface methods + * @compile -XDallowStaticInterfaceMethods StaticImport1.java */ -import java.lang.annotation.*; +import static pkg.A.*; -@interface Foos { - MissingContainerFor[] value(); +class StaticImport1 { + void test() { + m(); + } } - -@ContainedBy(Foos.class) -public @interface MissingContainerFor {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport2.java similarity index 76% rename from langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java rename to langtools/test/tools/javac/defaultMethods/static/import/StaticImport2.java index c87bdbcc40b..53ab19a3317 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java +++ b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport2.java @@ -21,19 +21,18 @@ * questions. */ -/** +/* * @test - * @summary Smoke test for repeating annotations - * @compile/fail WrongContainerFor.java - * @bug 7151010 + * @bug 8005166 + * @summary Add support for static interface methods + * Smoke test for static imports of static interface methods + * @compile/fail/ref=StaticImport2.out -XDrawDiagnostics -XDallowStaticInterfaceMethods StaticImport2.java */ -import java.lang.annotation.*; +import static pkg.B.*; -@ContainerFor(Retention.class) -@interface Foos { - WrongContainerFor[] value(); +class StaticImport2 { + void test() { + m(); + } } - -@ContainedBy(Foos.class) -public @interface WrongContainerFor {} diff --git a/langtools/test/tools/javac/defaultMethods/static/import/StaticImport2.out b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport2.out new file mode 100644 index 00000000000..d21b3a9963e --- /dev/null +++ b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport2.out @@ -0,0 +1,2 @@ +StaticImport2.java:36:9: compiler.err.cant.resolve.location.args: kindname.method, m, , , (compiler.misc.location: kindname.class, StaticImport2, null) +1 error diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport3.java similarity index 76% rename from langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java rename to langtools/test/tools/javac/defaultMethods/static/import/StaticImport3.java index 182acf0534d..2eb6b0a60dd 100644 --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java +++ b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport3.java @@ -21,19 +21,18 @@ * questions. */ -/** +/* * @test - * @summary Smoke test for repeating annotations - * @compile/fail WrongContainedBy.java - * @bug 7151010 + * @bug 8005166 + * @summary Add support for static interface methods + * Smoke test for static imports of static interface methods + * @compile/fail/ref=StaticImport3.out -XDrawDiagnostics -XDallowStaticInterfaceMethods StaticImport3.java */ -import java.lang.annotation.*; +import static pkg.C.*; -@ContainerFor(WrongContainedBy.class) -@interface Foos { - WrongContainedBy[] value(); +class StaticImport3 { + void test() { + m(); + } } - -@ContainedBy(Target.class) -public @interface WrongContainedBy {} diff --git a/langtools/test/tools/javac/defaultMethods/static/import/StaticImport3.out b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport3.out new file mode 100644 index 00000000000..51bfb5d3971 --- /dev/null +++ b/langtools/test/tools/javac/defaultMethods/static/import/StaticImport3.out @@ -0,0 +1,2 @@ +StaticImport3.java:36:9: compiler.err.cant.resolve.location.args: kindname.method, m, , , (compiler.misc.location: kindname.class, StaticImport3, null) +1 error diff --git a/langtools/test/tools/javac/diags/examples/NoUniqueMaximalInstance.java b/langtools/test/tools/javac/defaultMethods/static/import/pkg/A.java similarity index 84% rename from langtools/test/tools/javac/diags/examples/NoUniqueMaximalInstance.java rename to langtools/test/tools/javac/defaultMethods/static/import/pkg/A.java index dc4a2e95169..d3f92fde24a 100644 --- a/langtools/test/tools/javac/diags/examples/NoUniqueMaximalInstance.java +++ b/langtools/test/tools/javac/defaultMethods/static/import/pkg/A.java @@ -21,11 +21,8 @@ * questions. */ -// key: compiler.err.prob.found.req -// key: compiler.misc.no.unique.maximal.instance.exists +package pkg; -class NoUniqueMaximalInstance { - Z m() { return null; } - - { String s = m(); } +public interface A { + static void m() { } } diff --git a/langtools/test/tools/javac/defaultMethods/static/import/pkg/B.java b/langtools/test/tools/javac/defaultMethods/static/import/pkg/B.java new file mode 100644 index 00000000000..5b285062746 --- /dev/null +++ b/langtools/test/tools/javac/defaultMethods/static/import/pkg/B.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg; + +public interface B extends A { } diff --git a/langtools/test/tools/javac/defaultMethods/static/import/pkg/C.java b/langtools/test/tools/javac/defaultMethods/static/import/pkg/C.java new file mode 100644 index 00000000000..46d5159db61 --- /dev/null +++ b/langtools/test/tools/javac/defaultMethods/static/import/pkg/C.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg; + +public class C implements A { } diff --git a/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java b/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java index f081e2c9290..9c3a513c90f 100644 --- a/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java +++ b/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java @@ -23,17 +23,21 @@ /* * @test + * @bug 8006694 * @summary Automatic test for checking correctness of default super/this resolution + * temporarily workaround combo tests are causing time out in several platforms * @library ../../lib * @build JavacTestingAbstractThreadedTest - * @run main TestDefaultSuperCall + * @run main/othervm TestDefaultSuperCall */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; @@ -212,7 +216,6 @@ public class TestDefaultSuperCall List elementsWithMethod; Shape(ElementKind... elements) { - errWriter.println("elements = " + Arrays.toString(elements)); enclosingElements = new ArrayList<>(); enclosingNames = new ArrayList<>(); elementsWithMethod = new ArrayList<>(); @@ -406,7 +409,6 @@ public class TestDefaultSuperCall public void report(Diagnostic diagnostic) { if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { - errWriter.println(diagnostic.getMessage(Locale.getDefault())); errorFound = true; } } diff --git a/langtools/test/tools/javac/defaultMethods/syntax/TestDefaultMethodsSyntax.java b/langtools/test/tools/javac/defaultMethods/syntax/TestDefaultMethodsSyntax.java index c67146474fa..e720f37bb83 100644 --- a/langtools/test/tools/javac/defaultMethods/syntax/TestDefaultMethodsSyntax.java +++ b/langtools/test/tools/javac/defaultMethods/syntax/TestDefaultMethodsSyntax.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7192245 + * @bug 7192245 8005851 8005166 * @summary Automatic test for checking set of allowed modifiers on interface methods */ @@ -54,7 +54,7 @@ public class TestDefaultMethodsSyntax { } List getOptions() { - return Arrays.asList("-source", versionString); + return Arrays.asList("-XDallowStaticInterfaceMethods", "-source", versionString); } } @@ -77,32 +77,6 @@ public class TestDefaultMethodsSyntax { this.modStr = modStr; } - boolean isAllowed(EnclosingKind ek, ModifierKind otherMod) { - if (this == otherMod) return false; - switch (this) { - case NONE: - return true; - case ABSTRACT: - return otherMod != PRIVATE; - case NATIVE: - return otherMod != ABSTRACT && - otherMod != STRICTFP; - case FINAL: - case STATIC: - case SYNCHRONIZED: - case STRICTFP: - return otherMod != ABSTRACT; - case PUBLIC: - return true; - case PROTECTED: - return ek == EnclosingKind.ABSTRACT_CLASS; - case DEFAULT: - return otherMod != ABSTRACT; - default: - return true; - } - } - static boolean intersect(ModifierKind mk, ModifierKind... mks) { for (ModifierKind mk2 : mks) { if (mk == mk2) return true; @@ -113,7 +87,7 @@ public class TestDefaultMethodsSyntax { static boolean compatible(MethodKind mk, ModifierKind mod1, ModifierKind mod2, EnclosingKind ek) { if (intersect(ABSTRACT, mod1, mod2) || intersect(NATIVE, mod1, mod2)) { return mk == MethodKind.NO_BODY; - } else if (intersect(DEFAULT, mod1, mod2)) { + } else if (intersect(DEFAULT, mod1, mod2) || intersect(STATIC, mod1, mod2)) { return mk == MethodKind.BODY; } else { return ek == EnclosingKind.INTERFACE ? @@ -123,7 +97,6 @@ public class TestDefaultMethodsSyntax { boolean compatible(EnclosingKind ek) { switch (this) { - case STATIC: case PRIVATE: case PROTECTED: return ek != EnclosingKind.INTERFACE; @@ -176,17 +149,17 @@ public class TestDefaultMethodsSyntax { static Result[][] allowedModifierPairs = { /* NONE PUBLIC PROTECTED PRIVATE ABSTRACT STATIC NATIVE SYNCHRONIZED FINAL STRICTFP DEFAULT */ - /* NONE */ { T , T , C , C , T , C , C , C , C , C , I }, - /* PUBLIC */ { T , F , F , F , T , C , C , C , C , C , I }, + /* NONE */ { T , T , C , C , T , T , C , C , C , C , I }, + /* PUBLIC */ { T , F , F , F , T , T , C , C , C , C , I }, /* PROTECTED */ { C , F , F , F , C , C , C , C , C , C , F }, /* PRIVATE */ { C , F , F , F , F , C , C , C , C , C , F }, /* ABSTRACT */ { T , T , C , F , F , F , F , F , F , F , F }, - /* STATIC */ { C , C , C , C , F , F , C , C , C , C , F }, + /* STATIC */ { T , T , C , C , F , F , C , C , C , T , F }, /* NATIVE */ { C , C , C , C , F , C , F , C , C , F , F }, - /* SYNCHRONIZED */ { C , C , C , C , F , C , C , F , C , C , I }, + /* SYNCHRONIZED */ { C , C , C , C , F , C , C , F , C , C , F }, /* FINAL */ { C , C , C , C , F , C , C , C , F , C , F }, - /* STRICTFP */ { C , C , C , C , F , C , F , C , C , F , I }, - /* DEFAULT */ { I , I , F , F , F , F , F , I , F , I , F }}; + /* STRICTFP */ { C , C , C , C , F , T , F , C , C , F , I }, + /* DEFAULT */ { I , I , F , F , F , F , F , F , F , I , F }}; } enum MethodKind { @@ -291,6 +264,9 @@ public class TestDefaultMethodsSyntax { errorExpected |= ModifierKind.intersect(ModifierKind.DEFAULT, modk1, modk2) && vk == VersionKind.PRE_LAMBDA; + errorExpected |= ModifierKind.intersect(ModifierKind.STATIC, modk1, modk2) && + ek == EnclosingKind.INTERFACE && vk == VersionKind.PRE_LAMBDA; + checkCount++; if (diagChecker.errorFound != errorExpected) { throw new AssertionError("Problem when compiling source:\n" + source.getCharContent(true) + diff --git a/langtools/test/tools/javac/diags/CheckResourceKeys.java b/langtools/test/tools/javac/diags/CheckResourceKeys.java index 4c10b1a9878..bb9e10bd7cf 100644 --- a/langtools/test/tools/javac/diags/CheckResourceKeys.java +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -200,6 +200,7 @@ public class CheckResourceKeys { Set needToInvestigate = new TreeSet(Arrays.asList( + "compiler.misc.fatal.err.cant.close.loader", // Supressed by JSR308 "compiler.err.cant.read.file", // UNUSED "compiler.err.illegal.self.ref", // UNUSED "compiler.err.io.exception", // UNUSED diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 061825ac0d2..437d61d2406 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -1,13 +1,14 @@ compiler.err.already.annotated # internal compiler error? compiler.err.already.defined.this.unit # seems to be masked by compiler.err.duplicate.class compiler.err.annotation.value.not.allowable.type # cannot happen: precluded by complete type-specific tests +compiler.err.bad.functional.intf.anno # seems to be masked by compiler.err.annotation.type.not.applicable compiler.err.cant.read.file # (apt.JavaCompiler?) compiler.err.cant.select.static.class.from.param.type compiler.err.dc.unterminated.string # cannot happen compiler.err.illegal.char.for.encoding -compiler.err.invalid.containedby.annotation # should not happen -compiler.err.invalid.containedby.annotation.invalid.value # "can't" happen -compiler.err.invalid.containedby.annotation.multiple.values # can't happen +compiler.err.invalid.repeatable.annotation # should not happen +compiler.err.invalid.repeatable.annotation.invalid.value # "can't" happen +compiler.err.invalid.repeatable.annotation.multiple.values # can't happen compiler.err.io.exception # (javah.JavahTask?) compiler.err.limit.code # Code compiler.err.limit.code.too.large.for.try.stmt # Gen @@ -47,6 +48,7 @@ compiler.misc.bad.enclosing.class # bad class file compiler.misc.bad.enclosing.method # bad class file compiler.misc.bad.runtime.invisible.param.annotations # bad class file compiler.misc.bad.signature # bad class file +compiler.misc.bad.type.annotation.value compiler.misc.base.membership # UNUSED compiler.misc.ccf.found.later.version compiler.misc.ccf.unrecognized.attribute @@ -58,6 +60,7 @@ compiler.misc.fatal.err.cant.locate.meth # Resolve, from Lower compiler.misc.fatal.err.cant.close # JavaCompiler compiler.misc.file.does.not.contain.package compiler.misc.illegal.start.of.class.file +compiler.misc.inferred.do.not.conform.to.lower.bounds # cannot happen? compiler.misc.kindname.annotation compiler.misc.kindname.enum compiler.misc.kindname.package @@ -67,6 +70,7 @@ compiler.misc.kindname.type.variable.bound compiler.misc.kindname.value compiler.misc.incompatible.eq.lower.bounds # cannot happen? compiler.misc.no.unique.minimal.instance.exists +compiler.misc.no.unique.maximal.instance.exists # cannot happen? compiler.misc.resume.abort # prompt for a response compiler.misc.source.unavailable # DiagnosticSource compiler.misc.token.bad-symbol diff --git a/langtools/test/tools/javac/diags/examples/BadFunctionalIntfAnno.java b/langtools/test/tools/javac/diags/examples/BadFunctionalIntfAnno.java new file mode 100644 index 00000000000..87090505bd2 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/BadFunctionalIntfAnno.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 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. + */ + +// key: compiler.err.bad.functional.intf.anno.1 +// key: compiler.misc.not.a.functional.intf + +@FunctionalInterface +class BadFunctionalIntfAnno { } diff --git a/langtools/test/tools/javac/diags/examples/WrongContainerFor.java b/langtools/test/tools/javac/diags/examples/CantAnnotateNestedType.java similarity index 75% rename from langtools/test/tools/javac/diags/examples/WrongContainerFor.java rename to langtools/test/tools/javac/diags/examples/CantAnnotateNestedType.java index e439b780fbe..30d4572e601 100644 --- a/langtools/test/tools/javac/diags/examples/WrongContainerFor.java +++ b/langtools/test/tools/javac/diags/examples/CantAnnotateNestedType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,15 +21,21 @@ * questions. */ -// key: compiler.err.invalid.container.wrong.containerfor -// key: compiler.err.invalid.container.no.containedby +// key: compiler.err.cant.annotate.nested.type import java.lang.annotation.*; -@ContainerFor(Retention.class) -@interface Foos { - WrongContainerFor[] value(); -} +class CantAnnotateStaticClass { + @Target(ElementType.TYPE_USE) + @interface A {} -@ContainedBy(Foos.class) -public @interface WrongContainerFor {} + interface Outer { + interface Inner {} + } + + // Error: + @A Outer.Inner f; + + // OK: + @A Outer g; +} diff --git a/langtools/test/tools/javac/diags/examples/CantAnnotateStaticClass.java b/langtools/test/tools/javac/diags/examples/CantAnnotateStaticClass.java new file mode 100644 index 00000000000..d3505bbd461 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/CantAnnotateStaticClass.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 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. + */ + +// key: compiler.err.cant.annotate.static.class + +import java.lang.annotation.*; + +class CantAnnotateStaticClass { + @Target(ElementType.TYPE_USE) + @interface A {} + + static class Outer { + class Inner {} + } + + // Error: + @A Outer.Inner f; + + // OK: + @A Outer g; +} diff --git a/langtools/test/tools/javac/diags/examples/CyclicInference.java b/langtools/test/tools/javac/diags/examples/CyclicInference.java index cc929332404..0a6bc7a2b82 100644 --- a/langtools/test/tools/javac/diags/examples/CyclicInference.java +++ b/langtools/test/tools/javac/diags/examples/CyclicInference.java @@ -21,7 +21,7 @@ * questions. */ -// key: compiler.err.cant.apply.symbol +// key: compiler.err.prob.found.req // key: compiler.misc.cyclic.inference class CyclicInference { diff --git a/langtools/test/tools/javac/diags/examples/IllegalStaticIntfMethCall.java b/langtools/test/tools/javac/diags/examples/IllegalStaticIntfMethCall.java new file mode 100644 index 00000000000..29fa0bb1259 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/IllegalStaticIntfMethCall.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.illegal.static.intf.meth.call +// options: -XDallowStaticInterfaceMethods + +class IllegalStaticIntfMethCall { + interface A { + static void m() { } + } + void test(A a) { + a.m(); + } +} diff --git a/langtools/test/tools/javac/diags/examples/IncorrectReceiverType.java b/langtools/test/tools/javac/diags/examples/IncorrectReceiverType.java new file mode 100644 index 00000000000..548067b503b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/IncorrectReceiverType.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012, 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. + */ + +// key: compiler.err.incorrect.receiver.type + +class IncorrectReceiverType { + void m(Object this) {} +} diff --git a/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java b/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java index 1dcc0997961..4d2cf299b00 100644 --- a/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java +++ b/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -22,17 +22,16 @@ */ // key: compiler.err.duplicate.annotation.invalid.repeated -// key: compiler.err.invalid.containedby.annotation.elem.nondefault -// +// key: compiler.err.invalid.repeatable.annotation.elem.nondefault + // We need an almost valid containing annotation. The easiest way to get // one close enough to valid is by forgetting a default. import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); String foo(); } @Anno diff --git a/langtools/test/tools/javac/diags/examples/NoAnnotationsOnDotClass.java b/langtools/test/tools/javac/diags/examples/NoAnnotationsOnDotClass.java new file mode 100644 index 00000000000..0ce65530e6f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NoAnnotationsOnDotClass.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012, 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. + */ + +// key: compiler.err.no.annotations.on.dot.class + +class NoAnnotationsOnDotClass { + @Target(ElementType.TYPE_USE) + @interface A {} + + Object o = @A Object.class; +} diff --git a/langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java b/langtools/test/tools/javac/diags/examples/RepeatableDocumentedMismatch.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java rename to langtools/test/tools/javac/diags/examples/RepeatableDocumentedMismatch.java index a5077c7b825..0329acfc476 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableDocumentedMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,17 +21,16 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.not.documented +// key: compiler.err.invalid.repeatable.annotation.not.documented import java.lang.annotation.*; @Documented -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } @Anno @Anno -class ContainedByDocumentedMismatch { } +class RepeatableDocumentedMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java b/langtools/test/tools/javac/diags/examples/RepeatableInheritedMismatch.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java rename to langtools/test/tools/javac/diags/examples/RepeatableInheritedMismatch.java index d7723bad61c..57ad1705859 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableInheritedMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,17 +21,16 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.not.inherited +// key: compiler.err.invalid.repeatable.annotation.not.inherited import java.lang.annotation.*; @Inherited -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } @Anno @Anno -class ContainedByInheritedMismatch { } +class RepeatableInheritedMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByNoValue.java b/langtools/test/tools/javac/diags/examples/RepeatableNoValue.java similarity index 83% rename from langtools/test/tools/javac/diags/examples/ContainedByNoValue.java rename to langtools/test/tools/javac/diags/examples/RepeatableNoValue.java index 8cb612808f9..01f88717bca 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByNoValue.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableNoValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,16 +21,15 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.no.value +// key: compiler.err.invalid.repeatable.annotation.no.value import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos {} @Anno @Anno -class ContainedByNoValue { } +class RepeatableNoValue { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java b/langtools/test/tools/javac/diags/examples/RepeatableNonDefault.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java rename to langtools/test/tools/javac/diags/examples/RepeatableNonDefault.java index d6006dedfe3..bbf2ce57211 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableNonDefault.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,14 +21,13 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.elem.nondefault +// key: compiler.err.invalid.repeatable.annotation.elem.nondefault import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); String foo(); } -class ContainedByNonDefault { } +class RepeatableNonDefault { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java b/langtools/test/tools/javac/diags/examples/RepeatableRetentionMismatch.java similarity index 83% rename from langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java rename to langtools/test/tools/javac/diags/examples/RepeatableRetentionMismatch.java index 22680f5b644..47a19e2696f 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableRetentionMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,17 +21,16 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.retention +// key: compiler.err.invalid.repeatable.annotation.retention import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } @Anno @Anno -class ContainedByRetentionMismatch { } +class RepeatableRetentionMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java b/langtools/test/tools/javac/diags/examples/RepeatableTargetMismatch.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java rename to langtools/test/tools/javac/diags/examples/RepeatableTargetMismatch.java index 3fcd4fb3f5d..d16cad28f70 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableTargetMismatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,15 +21,14 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.incompatible.target +// key: compiler.err.invalid.repeatable.annotation.incompatible.target import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @Target(ElementType.METHOD) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } -class ContainedByTargetMismatch { } +class RepeatableTargetMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java b/langtools/test/tools/javac/diags/examples/RepeatableWrongValueType.java similarity index 82% rename from langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java rename to langtools/test/tools/javac/diags/examples/RepeatableWrongValueType.java index 9b963bd3f6e..583e01532b1 100644 --- a/langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java +++ b/langtools/test/tools/javac/diags/examples/RepeatableWrongValueType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,16 +21,15 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.value.return +// key: compiler.err.invalid.repeatable.annotation.value.return import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { String value(); } @Anno @Anno -class ContainedByWrongValueType { } +class RepeatableWrongValueType { } diff --git a/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java b/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java index 07a9bfddefb..dec4b59649a 100644 --- a/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java +++ b/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -21,14 +21,13 @@ * questions. */ -// key: compiler.err.invalid.containedby.annotation.repeated.and.container.present +// key: compiler.err.invalid.repeatable.annotation.repeated.and.container.present import java.lang.annotation.*; -@ContainedBy(Annos.class) +@Repeatable(Annos.class) @interface Anno { } -@ContainerFor(Anno.class) @interface Annos { Anno[] value(); } @Anno diff --git a/langtools/test/tools/javac/diags/examples/SecondaryBoundMustBeMarkerIntf.java b/langtools/test/tools/javac/diags/examples/SecondaryBoundMustBeMarkerIntf.java index 2520f8fb00c..c093974064b 100644 --- a/langtools/test/tools/javac/diags/examples/SecondaryBoundMustBeMarkerIntf.java +++ b/langtools/test/tools/javac/diags/examples/SecondaryBoundMustBeMarkerIntf.java @@ -23,7 +23,6 @@ // key: compiler.err.prob.found.req // key: compiler.misc.secondary.bound.must.be.marker.intf -// options: -XDallowIntersectionTypes class SecondaryBoundMustBeMarkerInterface { Runnable r = (Runnable & Comparable)()->{}; diff --git a/langtools/test/tools/javac/diags/examples/InferredDoNotConformToLower.java b/langtools/test/tools/javac/diags/examples/StaticIntfMethodNotSupported.java similarity index 80% rename from langtools/test/tools/javac/diags/examples/InferredDoNotConformToLower.java rename to langtools/test/tools/javac/diags/examples/StaticIntfMethodNotSupported.java index 5ab8024a86d..4cd3061866a 100644 --- a/langtools/test/tools/javac/diags/examples/InferredDoNotConformToLower.java +++ b/langtools/test/tools/javac/diags/examples/StaticIntfMethodNotSupported.java @@ -21,12 +21,9 @@ * questions. */ -// key: compiler.err.prob.found.req -// key: compiler.misc.inferred.do.not.conform.to.lower.bounds +// key: compiler.err.static.intf.methods.not.supported.in.source +// options: -source 7 -Xlint:-options -XDallowStaticInterfaceMethods -import java.util.*; - -class InferredDoNotConformToLower { - List m() { return null; } - { List lss = this.m(); } +interface StaticIntfMethodNotSupported { + static void m() { } } diff --git a/langtools/test/tools/javac/diags/examples/ThisAsIdentifier.java b/langtools/test/tools/javac/diags/examples/ThisAsIdentifier.java new file mode 100644 index 00000000000..cb3be6172dc --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ThisAsIdentifier.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012, 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. + */ + +// key: compiler.err.this.as.identifier + +class ThisAsIdentifier { + Object this; +} diff --git a/langtools/test/tools/javac/diags/examples/TypeAnnotationsNotSupported.java b/langtools/test/tools/javac/diags/examples/TypeAnnotationsNotSupported.java new file mode 100644 index 00000000000..16e6b8b51d3 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/TypeAnnotationsNotSupported.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +// key: compiler.err.type.annotations.not.supported.in.source +// key: compiler.warn.source.no.bootclasspath +// options: -source 6 + +@interface Anno { } + +class TypeAnnotationsNotSupported { + void m() { + int i = (@Anno int) 3.14; + } +} diff --git a/langtools/test/tools/javac/diags/examples/UnderscoreAsIdentifier.java b/langtools/test/tools/javac/diags/examples/UnderscoreAsIdentifier.java new file mode 100644 index 00000000000..91c939cf37f --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/UnderscoreAsIdentifier.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 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. + */ + +// key: compiler.warn.underscore.as.identifier + +class UnderscoreAsIdentifier { + String _ = null; +} diff --git a/langtools/test/tools/javac/diags/examples/WhereIntersection.java b/langtools/test/tools/javac/diags/examples/WhereIntersection.java index cb72d7324ec..b8b94f829e7 100644 --- a/langtools/test/tools/javac/diags/examples/WhereIntersection.java +++ b/langtools/test/tools/javac/diags/examples/WhereIntersection.java @@ -25,7 +25,7 @@ // key: compiler.misc.where.description.intersection // key: compiler.misc.intersection.type // key: compiler.err.prob.found.req -// key: compiler.misc.inconvertible.types +// key: compiler.misc.inferred.do.not.conform.to.upper.bounds // options: -XDdiags=where // run: simple diff --git a/langtools/test/tools/javac/diags/examples/WrongContainedBy.java b/langtools/test/tools/javac/diags/examples/WrongContainedBy.java deleted file mode 100644 index 6914c4bd64e..00000000000 --- a/langtools/test/tools/javac/diags/examples/WrongContainedBy.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// key: compiler.err.invalid.container.no.containerfor -// key: compiler.err.invalid.container.wrong.containedby - -import java.lang.annotation.*; - -@ContainerFor(WrongContainedBy.class) -@interface Foos { - WrongContainedBy[] value(); -} - -@ContainedBy(Target.class) -public @interface WrongContainedBy {} diff --git a/langtools/test/tools/javac/failover/CheckAttributedTree.java b/langtools/test/tools/javac/failover/CheckAttributedTree.java index f664995d107..8f7fc379a18 100644 --- a/langtools/test/tools/javac/failover/CheckAttributedTree.java +++ b/langtools/test/tools/javac/failover/CheckAttributedTree.java @@ -23,13 +23,17 @@ /* * @test - * @bug 6970584 + * @bug 6970584 8006694 * @summary assorted position errors in compiler syntax trees + * temporarily workaround combo tests are causing time out in several platforms * @library ../lib * @build JavacTestingAbstractThreadedTest - * @run main CheckAttributedTree -q -r -et ERRONEOUS . + * @run main/othervm 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; @@ -358,11 +362,18 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { } Info self = new Info(tree, endPosTable); - check(!mandatoryType(tree) || - (tree.type != null && - checkFields(tree)), - "'null' found in tree ", - self); + if (mandatoryType(tree)) { + check(tree.type != null, + "'null' field 'type' found in tree ", self); + if (tree.type==null) + new Throwable().printStackTrace(); + } + + Field errField = checkFields(tree); + if (errField!=null) { + check(false, + "'null' field '" + errField.getName() + "' found in tree ", self); + } Info prevEncl = encl; encl = self; @@ -391,7 +402,7 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { } } - boolean checkFields(JCTree t) { + Field checkFields(JCTree t) { List fieldsToCheck = treeUtil.getFieldsOfType(t, excludedFields, Symbol.class, @@ -399,7 +410,7 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { for (Field f : fieldsToCheck) { try { if (f.get(t) == null) { - return false; + return f; } } catch (IllegalAccessException e) { @@ -407,7 +418,7 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { //swallow it } } - return true; + return null; } @Override @@ -505,7 +516,7 @@ public class CheckAttributedTree extends JavacTestingAbstractThreadedTest { } public void report(Diagnostic diagnostic) { - out.println(diagnostic); + //out.println(diagnostic); switch (diagnostic.getKind()) { case ERROR: errors++; diff --git a/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java b/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java index 2d8fea2c13d..b50c4effe40 100644 --- a/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java +++ b/langtools/test/tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java @@ -23,13 +23,17 @@ /* * @test - * @bug 7046778 + * @bug 7046778 8006694 * @summary Project Coin: problem with diamond and member inner classes + * temporarily workaround combo tests are causing time out in several platforms * @library ../../../lib * @build JavacTestingAbstractThreadedTest - * @run main DiamondAndInnerClassTest + * @run main/othervm 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.util.Arrays; diff --git a/langtools/test/tools/javac/generics/diamond/T6939780.out b/langtools/test/tools/javac/generics/diamond/T6939780.out index 5fe51e6c217..85ffab546d9 100644 --- a/langtools/test/tools/javac/generics/diamond/T6939780.out +++ b/langtools/test/tools/javac/generics/diamond/T6939780.out @@ -1,3 +1,4 @@ +T6939780.java:18:33: compiler.warn.diamond.redundant.args: Foo, Foo T6939780.java:19:28: compiler.warn.diamond.redundant.args: Foo, Foo T6939780.java:20:28: compiler.warn.diamond.redundant.args.1: Foo, Foo -2 warnings +3 warnings diff --git a/langtools/test/tools/javac/generics/diamond/neg/Neg05.out b/langtools/test/tools/javac/generics/diamond/neg/Neg05.out index d6fca256bd5..7ab2ece7e0e 100644 --- a/langtools/test/tools/javac/generics/diamond/neg/Neg05.out +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg05.out @@ -1,25 +1,25 @@ Neg05.java:19:48: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:19:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo, Neg05.Foo) Neg05.java:20:58: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:20:45: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo, Neg05.Foo) Neg05.java:21:43: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:21:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo, Neg05.Foo) Neg05.java:22:56: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:22:43: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo, Neg05.Foo) Neg05.java:24:48: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:24:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo, Neg05.Foo) Neg05.java:25:58: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:25:45: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo, Neg05.Foo) Neg05.java:26:43: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:26:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo, Neg05.Foo) Neg05.java:27:56: compiler.err.improperly.formed.type.inner.raw.param -Neg05.java:27:43: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg05.Foo, Neg05.Foo) Neg05.java:31:37: compiler.err.improperly.formed.type.inner.raw.param +Neg05.java:31:44: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V, Neg05.Foo, Neg05.Foo)) Neg05.java:32:47: compiler.err.improperly.formed.type.inner.raw.param +Neg05.java:32:54: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V, Neg05.Foo, Neg05.Foo)) Neg05.java:33:32: compiler.err.improperly.formed.type.inner.raw.param +Neg05.java:33:39: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V, Neg05.Foo, Neg05.Foo)) Neg05.java:34:45: compiler.err.improperly.formed.type.inner.raw.param +Neg05.java:34:52: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V, Neg05.Foo, Neg05.Foo)) Neg05.java:36:37: compiler.err.improperly.formed.type.inner.raw.param +Neg05.java:36:44: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V,Z, Neg05.Foo, Neg05.Foo)) Neg05.java:37:47: compiler.err.improperly.formed.type.inner.raw.param +Neg05.java:37:54: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V,Z, Neg05.Foo, Neg05.Foo)) Neg05.java:38:32: compiler.err.improperly.formed.type.inner.raw.param +Neg05.java:38:39: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V,Z, Neg05.Foo, Neg05.Foo)) Neg05.java:39:45: compiler.err.improperly.formed.type.inner.raw.param +Neg05.java:39:52: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg05.Foo), (compiler.misc.infer.no.conforming.instance.exists: V,Z, Neg05.Foo, Neg05.Foo)) 24 errors diff --git a/langtools/test/tools/javac/generics/diamond/neg/Neg10.java b/langtools/test/tools/javac/generics/diamond/neg/Neg10.java index d8f9a18cee3..5bae2b0fc3e 100644 --- a/langtools/test/tools/javac/generics/diamond/neg/Neg10.java +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg10.java @@ -4,7 +4,8 @@ * * @summary Check that 'complex' diamond can infer type that is too specific * @author mcimadamore - * @compile/fail/ref=Neg10.out Neg10.java -XDrawDiagnostics + * @compile/fail/ref=Neg10.out -source 7 -Xlint:-options Neg10.java -XDrawDiagnostics + * @compile Neg10.java -XDrawDiagnostics * */ diff --git a/langtools/test/tools/javac/generics/diamond/neg/Neg10.out b/langtools/test/tools/javac/generics/diamond/neg/Neg10.out index 204d2bf5747..d5b323e04ee 100644 --- a/langtools/test/tools/javac/generics/diamond/neg/Neg10.out +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg10.out @@ -1,2 +1,2 @@ -Neg10.java:16:22: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg10.Foo, Neg10.Foo) +Neg10.java:17:22: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Neg10.Foo, Neg10.Foo) 1 error diff --git a/langtools/test/tools/javac/generics/inference/6315770/T6315770.out b/langtools/test/tools/javac/generics/inference/6315770/T6315770.out index 7178621922f..933cf7359f5 100644 --- a/langtools/test/tools/javac/generics/inference/6315770/T6315770.out +++ b/langtools/test/tools/javac/generics/inference/6315770/T6315770.out @@ -1,3 +1,3 @@ -T6315770.java:16:42: compiler.err.prob.found.req: (compiler.misc.no.unique.maximal.instance.exists: T, java.lang.String,java.lang.Integer,java.lang.Runnable) -T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.Integer&java.lang.Runnable, java.lang.String) +T6315770.java:16:42: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: T, java.lang.String,java.lang.Integer,java.lang.Runnable) +T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Integer,java.lang.Runnable) 2 errors diff --git a/langtools/test/tools/javac/generics/inference/6638712/T6638712b.out b/langtools/test/tools/javac/generics/inference/6638712/T6638712b.out index 228ac9236a5..9f72699204c 100644 --- a/langtools/test/tools/javac/generics/inference/6638712/T6638712b.out +++ b/langtools/test/tools/javac/generics/inference/6638712/T6638712b.out @@ -1,2 +1,2 @@ -T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.String,java.lang.Object) +T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: T, java.lang.Integer, java.lang.String,java.lang.Object) 1 error diff --git a/langtools/test/tools/javac/generics/inference/6650759/T6650759m.out b/langtools/test/tools/javac/generics/inference/6650759/T6650759m.out index a2744864922..ee2582c80ae 100644 --- a/langtools/test/tools/javac/generics/inference/6650759/T6650759m.out +++ b/langtools/test/tools/javac/generics/inference/6650759/T6650759m.out @@ -1,2 +1,2 @@ -T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.Integer, java.lang.String) +T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Integer,java.lang.Object) 1 error diff --git a/langtools/test/tools/javac/generics/inference/8006692/T8006692.java b/langtools/test/tools/javac/generics/inference/8006692/T8006692.java new file mode 100644 index 00000000000..83597e3a48b --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/8006692/T8006692.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 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. + */ + +/** + * @test + * @bug 8006692 + * @summary jdk/test/java/util/Collections/BigBinarySearch.java fails to compile + * @compile T8006692.java + */ + +import java.util.*; + +class Test { + static void test(List l, int i) { + equal(i, Collections.binarySearch(l, l.get(i))); + } + static void equal(Object x, Object y) {} +} diff --git a/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java b/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java index 04f80d2d3c4..f18106838be 100644 --- a/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java +++ b/langtools/test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java @@ -23,14 +23,18 @@ /* * @test - * @bug 7062745 + * @bug 7062745 8006694 * @summary Regression: difference in overload resolution when two methods - * are maximally specific + * are maximally specific + * temporarily workaround combo tests are causing time out in several platforms * @library ../../../lib * @build JavacTestingAbstractThreadedTest - * @run main GenericOverrideTest + * @run main/othervm GenericOverrideTest */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import javax.tools.Diagnostic; diff --git a/langtools/test/tools/javac/lambda/BadConv03.out b/langtools/test/tools/javac/lambda/BadConv03.out index 078f304f413..210148069a8 100644 --- a/langtools/test/tools/javac/lambda/BadConv03.out +++ b/langtools/test/tools/javac/lambda/BadConv03.out @@ -1,2 +1,2 @@ -BadConv03.java:19:11: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, BadConv03.B)) +BadConv03.java:19:11: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: BadConv03.B, (compiler.misc.incompatible.abstracts: kindname.interface, BadConv03.B)) 1 error diff --git a/langtools/test/tools/javac/lambda/BadLambdaPos.out b/langtools/test/tools/javac/lambda/BadLambdaPos.out index b2436d9ca1a..d192495c9c6 100644 --- a/langtools/test/tools/javac/lambda/BadLambdaPos.out +++ b/langtools/test/tools/javac/lambda/BadLambdaPos.out @@ -4,6 +4,6 @@ BadLambdaPos.java:19:14: compiler.err.unexpected.lambda BadLambdaPos.java:23:18: compiler.err.unexpected.lambda BadLambdaPos.java:23:34: compiler.err.unexpected.lambda BadLambdaPos.java:24:21: compiler.err.unexpected.lambda -BadLambdaPos.java:28:22: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -BadLambdaPos.java:29:28: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +BadLambdaPos.java:28:22: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +BadLambdaPos.java:29:28: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) 8 errors diff --git a/langtools/test/tools/javac/lambda/BadTargetType.out b/langtools/test/tools/javac/lambda/BadTargetType.out index 8979631251b..122b4c833e4 100644 --- a/langtools/test/tools/javac/lambda/BadTargetType.out +++ b/langtools/test/tools/javac/lambda/BadTargetType.out @@ -1,5 +1,5 @@ -BadTargetType.java:16:24: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -BadTargetType.java:17:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -BadTargetType.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, java.lang.Object, @460, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf)) -BadTargetType.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, java.lang.Object, @489, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf)) +BadTargetType.java:16:24: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +BadTargetType.java:17:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +BadTargetType.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, java.lang.Object, @460, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: java.lang.Object)) +BadTargetType.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, java.lang.Object, @489, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: java.lang.Object)) 4 errors diff --git a/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.java b/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.java new file mode 100644 index 00000000000..49248a0e378 --- /dev/null +++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.java @@ -0,0 +1,33 @@ +/* + * @test /nodynamiccopyright/ + * @summary smoke test for functional interface annotation + * @compile/fail/ref=FunctionalInterfaceAnno.out -XDrawDiagnostics FunctionalInterfaceAnno.java + */ +class FunctionalInterfaceAnno { + @FunctionalInterface + static class A { } //not an interface + + @FunctionalInterface + static abstract class B { } //not an interface + + @FunctionalInterface + enum C { } //not an interface + + @FunctionalInterface + @interface D { } //not an interface + + @FunctionalInterface + interface E { } //no abstracts + + @FunctionalInterface + interface F { default void m() { } } //no abstracts + + @FunctionalInterface + interface G { String toString(); } //no abstracts + + @FunctionalInterface + interface H { void m(); void n(); } //incompatible abstracts + + @FunctionalInterface + interface I { void m(); } //ok +} diff --git a/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.out b/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.out new file mode 100644 index 00000000000..d6b8c398bc6 --- /dev/null +++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceAnno.out @@ -0,0 +1,9 @@ +FunctionalInterfaceAnno.java:7:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf: FunctionalInterfaceAnno.A) +FunctionalInterfaceAnno.java:10:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf: FunctionalInterfaceAnno.B) +FunctionalInterfaceAnno.java:13:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf: FunctionalInterfaceAnno.C) +FunctionalInterfaceAnno.java:16:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf: FunctionalInterfaceAnno.D) +FunctionalInterfaceAnno.java:19:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf.1: FunctionalInterfaceAnno.E, (compiler.misc.no.abstracts: kindname.interface, FunctionalInterfaceAnno.E)) +FunctionalInterfaceAnno.java:22:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf.1: FunctionalInterfaceAnno.F, (compiler.misc.no.abstracts: kindname.interface, FunctionalInterfaceAnno.F)) +FunctionalInterfaceAnno.java:25:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf.1: FunctionalInterfaceAnno.G, (compiler.misc.no.abstracts: kindname.interface, FunctionalInterfaceAnno.G)) +FunctionalInterfaceAnno.java:28:5: compiler.err.bad.functional.intf.anno.1: (compiler.misc.not.a.functional.intf.1: FunctionalInterfaceAnno.H, (compiler.misc.incompatible.abstracts: kindname.interface, FunctionalInterfaceAnno.H)) +8 errors diff --git a/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java b/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java index c5d13a7ce15..06db21564f6 100644 --- a/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java +++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java @@ -23,15 +23,19 @@ /** * @test - * @bug 8003280 8004102 + * @bug 8003280 8004102 8006694 * @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 * @build JavacTestingAbstractThreadedTest - * @run main FunctionalInterfaceConversionTest + * @run main/othervm 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; diff --git a/langtools/test/tools/javac/lambda/Intersection01.java b/langtools/test/tools/javac/lambda/Intersection01.java index a04950eaff5..0745c73ce40 100644 --- a/langtools/test/tools/javac/lambda/Intersection01.java +++ b/langtools/test/tools/javac/lambda/Intersection01.java @@ -25,7 +25,7 @@ * @test * @bug 8002099 * @summary Add support for intersection types in cast expression - * @compile/fail/ref=Intersection01.out -XDallowIntersectionTypes -XDrawDiagnostics Intersection01.java + * @compile/fail/ref=Intersection01.out -XDrawDiagnostics Intersection01.java */ class Intersection01 { diff --git a/langtools/test/tools/javac/lambda/Intersection01.out b/langtools/test/tools/javac/lambda/Intersection01.out index 122935b0913..75debb49693 100644 --- a/langtools/test/tools/javac/lambda/Intersection01.out +++ b/langtools/test/tools/javac/lambda/Intersection01.out @@ -1,3 +1,3 @@ -Intersection01.java:36:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable)) -Intersection01.java:38:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable)) +Intersection01.java:36:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: java.io.Serializable, (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable)) +Intersection01.java:38:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: java.io.Serializable, (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable)) 2 errors diff --git a/langtools/test/tools/javac/lambda/LambdaCapture06.java b/langtools/test/tools/javac/lambda/LambdaCapture06.java index 85a6feb0e23..99a72d26af6 100644 --- a/langtools/test/tools/javac/lambda/LambdaCapture06.java +++ b/langtools/test/tools/javac/lambda/LambdaCapture06.java @@ -23,7 +23,6 @@ /* * @test - * @ignore investigate as to whether code generation fails * @bug 8003280 * @summary Add lambda tests * Compiler crash when local inner class nested inside lambda captures local variables from enclosing scope diff --git a/langtools/test/tools/javac/lambda/LambdaConv09.out b/langtools/test/tools/javac/lambda/LambdaConv09.out index 1f99986794c..5265879d881 100644 --- a/langtools/test/tools/javac/lambda/LambdaConv09.out +++ b/langtools/test/tools/javac/lambda/LambdaConv09.out @@ -1,5 +1,5 @@ -LambdaConv09.java:42:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo1)) -LambdaConv09.java:43:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo2)) -LambdaConv09.java:44:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo3)) -LambdaConv09.java:46:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo5)) +LambdaConv09.java:42:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: LambdaConv09.Foo1, (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo1)) +LambdaConv09.java:43:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: LambdaConv09.Foo2, (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo2)) +LambdaConv09.java:44:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: LambdaConv09.Foo3, (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo3)) +LambdaConv09.java:46:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: LambdaConv09.Foo5, (compiler.misc.no.abstracts: kindname.interface, LambdaConv09.Foo5)) 4 errors diff --git a/langtools/test/tools/javac/lambda/LambdaExpr10.out b/langtools/test/tools/javac/lambda/LambdaExpr10.out index adcba0ad43e..9270b144671 100644 --- a/langtools/test/tools/javac/lambda/LambdaExpr10.out +++ b/langtools/test/tools/javac/lambda/LambdaExpr10.out @@ -1,9 +1,9 @@ -LambdaExpr10.java:18:28: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:19:32: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:23:40: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:24:46: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:28:29: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -LambdaExpr10.java:29:33: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +LambdaExpr10.java:18:28: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:19:32: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:23:40: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:24:46: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:28:29: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) +LambdaExpr10.java:29:33: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) LambdaExpr10.java:33:35: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void)) LambdaExpr10.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void)) 8 errors diff --git a/langtools/test/tools/javac/lambda/LambdaExpr15.java b/langtools/test/tools/javac/lambda/LambdaExpr15.java index 3b38e8039b6..fd5f4e14bf0 100644 --- a/langtools/test/tools/javac/lambda/LambdaExpr15.java +++ b/langtools/test/tools/javac/lambda/LambdaExpr15.java @@ -23,7 +23,6 @@ /* * @test - * @ignore investigate as to whether code generation fails * @bug 8003280 * @summary Add lambda tests * check that nested inner class in statement lambdas don't get corrupted return statements diff --git a/langtools/test/tools/javac/lambda/LambdaExpr21.java b/langtools/test/tools/javac/lambda/LambdaExpr21.java new file mode 100644 index 00000000000..1d44e228ced --- /dev/null +++ b/langtools/test/tools/javac/lambda/LambdaExpr21.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @bug 8006684 + * @summary Compiler produces java.lang.VerifyError: Bad type on operand stack + * @run main LambdaExpr21 + */ +public class LambdaExpr21 { + + static int assertionCount = 0; + + static void assertTrue(boolean cond) { + assertionCount++; + if (!cond) + throw new AssertionError(); + } + + interface SAM { + void foo(); + } + + static class Checker { + Checker(boolean cond) { + assertTrue(cond); + } + } + + static { + SAM s = ()-> { new Checker(true) { }; }; + s.foo(); + } + + static void test(){ + SAM s = ()-> { new Checker(true) { }; }; + s.foo(); + } + + static SAM s = ()-> { new Checker(true) { }; }; + + public static void main(String[] args) { + test(); + s.foo(); + assertTrue(assertionCount == 3); + } +} diff --git a/langtools/test/tools/javac/lambda/LambdaParserTest.java b/langtools/test/tools/javac/lambda/LambdaParserTest.java index c4fb4f548a2..ae620279149 100644 --- a/langtools/test/tools/javac/lambda/LambdaParserTest.java +++ b/langtools/test/tools/javac/lambda/LambdaParserTest.java @@ -23,15 +23,18 @@ /* * @test - * @bug 7115050 - * @bug 8003280 + * @bug 7115050 8003280 8005852 8006694 * @summary Add lambda tests * Add parser support for lambda expressions + * temporarily workaround combo tests are causing time out in several platforms * @library ../lib * @build JavacTestingAbstractThreadedTest - * @run main LambdaParserTest + * @run main/othervm LambdaParserTest */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import javax.tools.Diagnostic; @@ -46,12 +49,12 @@ public class LambdaParserTest enum LambdaKind { NILARY_EXPR("()->x"), NILARY_STMT("()->{ return x; }"), - ONEARY_SHORT_EXPR("x->x"), - ONEARY_SHORT_STMT("x->{ return x; }"), - ONEARY_EXPR("(#M1 #T1 x)->x"), - ONEARY_STMT("(#M1 #T1 x)->{ return x; }"), - TWOARY_EXPR("(#M1 #T1 x, #M2 #T2 y)->x"), - TWOARY_STMT("(#M1 #T1 x, #M2 #T2 y)->{ 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; }"); String lambdaTemplate; @@ -60,11 +63,12 @@ public class LambdaParserTest } String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2, - ModifierKind mk1, ModifierKind mk2) { + 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("#T2", pk2.parameterType) + .replaceAll("#PN", pn.nameStr); } int arity() { @@ -87,6 +91,17 @@ public class LambdaParserTest } } + enum LambdaParameterName { + IDENT("x"), + UNDERSCORE("_"); + + String nameStr; + + LambdaParameterName(String nameStr) { + this.nameStr = nameStr; + } + } + enum LambdaParameterKind { IMPLICIT(""), EXPLIICT_SIMPLE("A"), @@ -151,8 +166,8 @@ public class LambdaParserTest } String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2, - ModifierKind mk1, ModifierKind mk2, LambdaKind lk, SubExprKind sk) { - return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2)) + 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); } } @@ -174,25 +189,27 @@ public class LambdaParserTest public static void main(String... args) throws Exception { for (LambdaKind lk : LambdaKind.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) + for (LambdaParameterName pn : LambdaParameterName.values()) { + for (LambdaParameterKind pk1 : LambdaParameterKind.values()) { + if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT) continue; - for (ModifierKind mk1 : ModifierKind.values()) { - if (mk1 != ModifierKind.NONE && lk.isShort()) + for (LambdaParameterKind pk2 : LambdaParameterKind.values()) { + if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT) continue; - if (lk.arity() < 1 && mk1 != ModifierKind.NONE) - continue; - for (ModifierKind mk2 : ModifierKind.values()) { - if (lk.arity() < 2 && mk2 != ModifierKind.NONE) + for (ModifierKind mk1 : ModifierKind.values()) { + if (mk1 != ModifierKind.NONE && lk.isShort()) continue; - for (SubExprKind sk : SubExprKind.values()) { - for (ExprKind ek : ExprKind.values()) { - pool.execute( - new LambdaParserTest(pk1, pk2, mk1, - mk2, lk, sk, ek)); + 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)); + } } } } @@ -209,6 +226,7 @@ public class LambdaParserTest ModifierKind mk1; ModifierKind mk2; LambdaKind lk; + LambdaParameterName pn; SubExprKind sk; ExprKind ek; JavaSource source; @@ -216,12 +234,13 @@ public class LambdaParserTest LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2, ModifierKind mk1, ModifierKind mk2, LambdaKind lk, - SubExprKind sk, ExprKind ek) { + 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(); @@ -239,7 +258,7 @@ public class LambdaParserTest public JavaSource() { super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); source = template.replaceAll("#E", - ek.expressionString(pk1, pk2, mk1, mk2, lk, sk)); + ek.expressionString(pk1, pk2, mk1, mk2, lk, pn, sk)); } @Override @@ -272,6 +291,9 @@ public class LambdaParserTest errorExpected = true; } + errorExpected |= pn == LambdaParameterName.UNDERSCORE && + lk.arity() > 0; + if (errorExpected != diagChecker.errorFound) { throw new Error("invalid diagnostics for source:\n" + source.getCharContent(true) + diff --git a/langtools/test/tools/javac/lambda/MethodReference04.out b/langtools/test/tools/javac/lambda/MethodReference04.out index 789804b78d5..46c933a12c2 100644 --- a/langtools/test/tools/javac/lambda/MethodReference04.out +++ b/langtools/test/tools/javac/lambda/MethodReference04.out @@ -1,2 +1,2 @@ -MethodReference04.java:13:16: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +MethodReference04.java:13:16: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) 1 error diff --git a/langtools/test/tools/javac/lambda/MethodReference25.java b/langtools/test/tools/javac/lambda/MethodReference25.java index cf180fcbac3..8f02359cf79 100644 --- a/langtools/test/tools/javac/lambda/MethodReference25.java +++ b/langtools/test/tools/javac/lambda/MethodReference25.java @@ -25,21 +25,13 @@ * @test * @bug 8003280 * @summary Add lambda tests - * check that non-boxing method references conversion has the precedence - * @run main MethodReference25 + * check that non-boxing method references is not preferred over boxing one + * @compile/fail/ref=MethodReference25.out -XDrawDiagnostics MethodReference25.java */ -public class MethodReference25 { +class MethodReference25 { - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - - static int assertionCount = 0; - - static void m(Integer i) { assertTrue(true); } + static void m(Integer i) { } interface SAM1 { void m(int x); @@ -49,11 +41,10 @@ public class MethodReference25 { void m(Integer x); } - static void call(int i, SAM1 s) { s.m(i); assertTrue(false); } + static void call(int i, SAM1 s) { s.m(i); } static void call(int i, SAM2 s) { s.m(i); } public static void main(String[] args) { - call(1, MethodReference25::m); //resolves to call(int, SAM2) - assertTrue(assertionCount == 1); + call(1, MethodReference25::m); //ambiguous } } diff --git a/langtools/test/tools/javac/lambda/MethodReference25.out b/langtools/test/tools/javac/lambda/MethodReference25.out new file mode 100644 index 00000000000..3b4e2674346 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference25.out @@ -0,0 +1,2 @@ +MethodReference25.java:48:9: compiler.err.ref.ambiguous: call, kindname.method, call(int,MethodReference25.SAM1), MethodReference25, kindname.method, call(int,MethodReference25.SAM2), MethodReference25 +1 error diff --git a/langtools/test/tools/javac/lambda/MethodReference26.java b/langtools/test/tools/javac/lambda/MethodReference26.java index 98b2540ff2e..29a4b5ebec8 100644 --- a/langtools/test/tools/javac/lambda/MethodReference26.java +++ b/langtools/test/tools/javac/lambda/MethodReference26.java @@ -1,9 +1,30 @@ /* - * @test /nodynamiccopyright/ - * @bug 8003280 - * @summary Add lambda tests - * check strict method conversion does not allow loose method reference conversion - * @compile/fail/ref=MethodReference26.out -XDrawDiagnostics MethodReference26.java + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary check strict method conversion allows loose method reference conversion + * @compile MethodReference26.java */ class MethodReference26 { @@ -18,6 +39,6 @@ class MethodReference26 { static void call(Integer i, SAM s) { } static void test() { - call(1, MethodReference26::m); //ambiguous + call(1, MethodReference26::m); //ok } } diff --git a/langtools/test/tools/javac/lambda/MethodReference26.out b/langtools/test/tools/javac/lambda/MethodReference26.out deleted file mode 100644 index 62b8bcfb09d..00000000000 --- a/langtools/test/tools/javac/lambda/MethodReference26.out +++ /dev/null @@ -1,2 +0,0 @@ -MethodReference26.java:21:9: compiler.err.ref.ambiguous: call, kindname.method, call(int,MethodReference26.SAM), MethodReference26, kindname.method, call(java.lang.Integer,MethodReference26.SAM), MethodReference26 -1 error diff --git a/langtools/test/tools/javac/lambda/MethodReference43.java b/langtools/test/tools/javac/lambda/MethodReference43.java index 17a50b91021..f7b8203d1b1 100644 --- a/langtools/test/tools/javac/lambda/MethodReference43.java +++ b/langtools/test/tools/javac/lambda/MethodReference43.java @@ -60,9 +60,9 @@ public class MethodReference43 { static void m(SAM1 s) { assertTrue(false); } - static void m(SAM2 s) { assertTrue(true); } + static void m(SAM2 s) { assertTrue(false); } static void m(SAM3 s) { assertTrue(false); } - static void m(SAM4 s) { assertTrue(false); } + static void m(SAM4 s) { assertTrue(true); } public static void main(String[] args) { m(Foo::new); diff --git a/langtools/test/tools/javac/lambda/MethodReference59.java b/langtools/test/tools/javac/lambda/MethodReference59.java new file mode 100644 index 00000000000..76b6669e313 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference59.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8004102 + * @summary Add support for array constructor references + */ +public class MethodReference59 { + + static int assertionCount = 0; + + static void assertTrue(boolean cond) { + assertionCount++; + if (!cond) + throw new AssertionError(); + } + + interface ArrayFactory { + X make(int size); + } + + public static void main(String[] args) { + ArrayFactory factory1 = int[]::new; + int[] i1 = factory1.make(5); + assertTrue(i1.length == 5); + ArrayFactory factory2 = int[][]::new; + int[][] i2 = factory2.make(5); + assertTrue(i2.length == 5); + assertTrue(assertionCount == 2); + } +} diff --git a/langtools/test/tools/javac/lambda/MethodReference60.java b/langtools/test/tools/javac/lambda/MethodReference60.java new file mode 100644 index 00000000000..f8317af36e2 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference60.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8004102 + * @summary Add support for array constructor references + * @compile/fail/ref=MethodReference60.out -XDrawDiagnostics MethodReference60.java + */ +public class MethodReference60 { + + interface ArrayFactory { + X make(int size); + } + + interface BadArrayFactory1 { + X make(); + } + + interface BadArrayFactory2 { + X make(int i1, int i2); + } + + interface BadArrayFactory3 { + X make(String s); + } + + public static void main(String[] args) { + BadArrayFactory1 factory1 = int[]::new; //param mismatch + BadArrayFactory2 factory2 = int[]::new; //param mismatch + BadArrayFactory3 factory3 = int[]::new; //param mismatch + ArrayFactory factory4 = int[]::new; //return type mismatch + ArrayFactory factory5 = int[]::new; //return type mismatch + } +} diff --git a/langtools/test/tools/javac/lambda/MethodReference60.out b/langtools/test/tools/javac/lambda/MethodReference60.out new file mode 100644 index 00000000000..5aa973cf2ad --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference60.out @@ -0,0 +1,6 @@ +MethodReference60.java:49:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, compiler.misc.no.args, kindname.class, Array, (compiler.misc.arg.length.mismatch))) +MethodReference60.java:50:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, int,int, kindname.class, Array, (compiler.misc.arg.length.mismatch))) +MethodReference60.java:51:44: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Array, int, java.lang.String, kindname.class, Array, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, int)))) +MethodReference60.java:52:42: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: int[], java.lang.Integer)) +MethodReference60.java:53:44: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: int[], java.lang.Integer[])) +5 errors diff --git a/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java b/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java index 7df1cc8983d..3366f902644 100644 --- a/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java +++ b/langtools/test/tools/javac/lambda/MethodReferenceParserTest.java @@ -24,14 +24,18 @@ /* * @test * @bug 7115052 - * @bug 8003280 + * @bug 8003280 8006694 * @summary Add lambda tests * Add parser support for method references + * temporarily workaround combo tests are causing time out in several platforms * @library ../lib * @build JavacTestingAbstractThreadedTest - * @run main MethodReferenceParserTest + * @run main/othervm MethodReferenceParserTest */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import javax.tools.Diagnostic; diff --git a/langtools/test/tools/javac/lambda/TargetType01.java b/langtools/test/tools/javac/lambda/TargetType01.java index 2b3f5434b16..68ec7671818 100644 --- a/langtools/test/tools/javac/lambda/TargetType01.java +++ b/langtools/test/tools/javac/lambda/TargetType01.java @@ -27,7 +27,7 @@ * @summary Add lambda tests * check nested case of overload resolution and lambda parameter inference * @author Maurizio Cimadamore - * @compile TargetType01.java + * @compile/fail/ref=TargetType01.out -XDrawDiagnostics TargetType01.java */ class TargetType01 { @@ -43,7 +43,6 @@ class TargetType01 { static String M(F_S_S f){ return null; } static { - //ambiguity here - the compiler does not try all the combinations! - M(x1 -> { return M( x2 -> { return x1 + x2; });}); + M(x1 -> { return M( x2 -> { return x1 + x2; });}); //ambiguous } } diff --git a/langtools/test/tools/javac/lambda/TargetType01.out b/langtools/test/tools/javac/lambda/TargetType01.out new file mode 100644 index 00000000000..2a2b286cc76 --- /dev/null +++ b/langtools/test/tools/javac/lambda/TargetType01.out @@ -0,0 +1,3 @@ +TargetType01.java:46:9: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01 +TargetType01.java:46:26: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01 +2 errors diff --git a/langtools/test/tools/javac/lambda/TargetType06.java b/langtools/test/tools/javac/lambda/TargetType06.java index 1a764156949..39aaf680f76 100644 --- a/langtools/test/tools/javac/lambda/TargetType06.java +++ b/langtools/test/tools/javac/lambda/TargetType06.java @@ -4,7 +4,7 @@ * @summary Add lambda tests * check complex case of target typing * @author Maurizio Cimadamore - * @compile/fail/ref=TargetType06.out -XDrawDiagnostics TargetType06.java + * @compile TargetType06.java */ import java.util.List; diff --git a/langtools/test/tools/javac/lambda/TargetType06.out b/langtools/test/tools/javac/lambda/TargetType06.out deleted file mode 100644 index ddfd542c129..00000000000 --- a/langtools/test/tools/javac/lambda/TargetType06.out +++ /dev/null @@ -1,2 +0,0 @@ -TargetType06.java:25:23: compiler.err.cant.apply.symbol: kindname.method, map, TargetType06.Function, @510, kindname.class, TargetType06, (compiler.misc.cyclic.inference: B) -1 error diff --git a/langtools/test/tools/javac/lambda/TargetType10.out b/langtools/test/tools/javac/lambda/TargetType10.out index fa904091c0e..eaf9bb3a07f 100644 --- a/langtools/test/tools/javac/lambda/TargetType10.out +++ b/langtools/test/tools/javac/lambda/TargetType10.out @@ -1,2 +1,2 @@ -TargetType10.java:17:11: compiler.err.cant.apply.symbol: kindname.method, compose, TargetType10.Function,TargetType10.Function, @500,@515, kindname.class, TargetType10.Test, (compiler.misc.cyclic.inference: B,A) +TargetType10.java:17:18: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: B,A) 1 error diff --git a/langtools/test/tools/javac/lambda/TargetType11.java b/langtools/test/tools/javac/lambda/TargetType11.java index 94ec8e9d536..99359aa301b 100644 --- a/langtools/test/tools/javac/lambda/TargetType11.java +++ b/langtools/test/tools/javac/lambda/TargetType11.java @@ -4,7 +4,7 @@ * @summary Add lambda tests * check that wildcards in the target method of a lambda conversion is handled correctly * @author Maurizio Cimadamore - * @compile/fail/ref=TargetType11.out -Xlint:unchecked -XDrawDiagnostics TargetType11.java + * @compile TargetType11.java */ class TargetType11 { diff --git a/langtools/test/tools/javac/lambda/TargetType11.out b/langtools/test/tools/javac/lambda/TargetType11.out deleted file mode 100644 index 01cf0cb1bcd..00000000000 --- a/langtools/test/tools/javac/lambda/TargetType11.out +++ /dev/null @@ -1,4 +0,0 @@ -TargetType11.java:16:61: compiler.warn.unchecked.varargs.non.reifiable.type: TargetType11.Predicate -TargetType11.java:20:32: compiler.err.cant.apply.symbol: kindname.method, and, TargetType11.Predicate[], @706,@718, kindname.class, TargetType11.Test, (compiler.misc.cyclic.inference: T) -1 error -1 warning diff --git a/langtools/test/tools/javac/lambda/TargetType14.out b/langtools/test/tools/javac/lambda/TargetType14.out index 0ca94aa932c..9de9a632646 100644 --- a/langtools/test/tools/javac/lambda/TargetType14.out +++ b/langtools/test/tools/javac/lambda/TargetType14.out @@ -1,2 +1,2 @@ -TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TargetType14.SAM, TargetType14.SAM) +TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.Integer, java.lang.String) 1 error diff --git a/langtools/test/tools/javac/lambda/TargetType17.out b/langtools/test/tools/javac/lambda/TargetType17.out index 0bb985f699b..2bdf33ce266 100644 --- a/langtools/test/tools/javac/lambda/TargetType17.out +++ b/langtools/test/tools/javac/lambda/TargetType17.out @@ -1,9 +1,9 @@ -TargetType17.java:14:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:15:23: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:16:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:17:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:18:23: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:19:25: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:20:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) -TargetType17.java:21:27: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +TargetType17.java:14:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: byte) +TargetType17.java:15:23: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: short) +TargetType17.java:16:19: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: int) +TargetType17.java:17:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: long) +TargetType17.java:18:23: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: float) +TargetType17.java:19:25: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: double) +TargetType17.java:20:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: char) +TargetType17.java:21:27: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: boolean) 8 errors diff --git a/langtools/test/tools/javac/lambda/TargetType21.java b/langtools/test/tools/javac/lambda/TargetType21.java index d916f50d5cb..ac70cacb6dc 100644 --- a/langtools/test/tools/javac/lambda/TargetType21.java +++ b/langtools/test/tools/javac/lambda/TargetType21.java @@ -26,8 +26,8 @@ class TargetType21 { void test() { call(x -> { throw new Exception(); }); //ambiguous - call(x -> { System.out.println(""); }); //ok - resolves to call(SAM2) - call(x -> { return (Object) null; }); //error - call(SAM3) is not applicable because of cyclic inference - call(x -> { return null; }); ////ok - resolves to call(SAM1) + call(x -> { System.out.println(""); }); //ambiguous + call(x -> { return (Object) null; }); //cyclic inference + call(x -> { return null; }); //ambiguous } } diff --git a/langtools/test/tools/javac/lambda/TargetType21.out b/langtools/test/tools/javac/lambda/TargetType21.out index 638b32f680c..1dd507822d0 100644 --- a/langtools/test/tools/javac/lambda/TargetType21.out +++ b/langtools/test/tools/javac/lambda/TargetType21.out @@ -1,3 +1,6 @@ -TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, call(TargetType21.SAM2), TargetType21 -TargetType21.java:30:9: compiler.err.cant.apply.symbols: kindname.method, call, @737,{(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM3), (compiler.misc.cyclic.inference: A))} -2 errors +TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 +TargetType21.java:28:14: compiler.err.incompatible.thrown.types.in.lambda: java.lang.Exception +TargetType21.java:29:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 +TargetType21.java:30:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: A) +TargetType21.java:31:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 +5 errors diff --git a/langtools/test/tools/javac/lambda/TargetType26.out b/langtools/test/tools/javac/lambda/TargetType26.out index 912df88f9f7..15cfc615f45 100644 --- a/langtools/test/tools/javac/lambda/TargetType26.out +++ b/langtools/test/tools/javac/lambda/TargetType26.out @@ -1,2 +1,2 @@ -TargetType26.java:16:7: compiler.err.cant.apply.symbol: kindname.method, call, Z, @340, kindname.class, TargetType26, (compiler.misc.cyclic.inference: Z) +TargetType26.java:16:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z) 1 error diff --git a/langtools/test/tools/javac/lambda/TargetType27.out b/langtools/test/tools/javac/lambda/TargetType27.out index 3edf2b92cb3..bf388592025 100644 --- a/langtools/test/tools/javac/lambda/TargetType27.out +++ b/langtools/test/tools/javac/lambda/TargetType27.out @@ -1,2 +1,2 @@ -TargetType27.java:18:9: compiler.err.cant.apply.symbol: kindname.method, m, TargetType27.F, @490, kindname.class, TargetType27, (compiler.misc.cyclic.inference: R) +TargetType27.java:18:10: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: R) 1 error diff --git a/langtools/test/tools/javac/lambda/TargetType28.out b/langtools/test/tools/javac/lambda/TargetType28.out index e157c4866ef..6b637239c34 100644 --- a/langtools/test/tools/javac/lambda/TargetType28.out +++ b/langtools/test/tools/javac/lambda/TargetType28.out @@ -1,3 +1,3 @@ -TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TargetType28.SuperFoo, TargetType28.SuperFoo) -TargetType28.java:21:33: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TargetType28.SuperFoo, TargetType28.SuperFoo) +TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Number, java.lang.Number,java.lang.String) +TargetType28.java:21:33: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Number, java.lang.Number,java.lang.Integer) 2 errors diff --git a/langtools/test/tools/javac/lambda/TargetType39.out b/langtools/test/tools/javac/lambda/TargetType39.out index c4eb33ef2d5..36a61bce0e2 100644 --- a/langtools/test/tools/javac/lambda/TargetType39.out +++ b/langtools/test/tools/javac/lambda/TargetType39.out @@ -1,3 +1,3 @@ -TargetType39.java:19:9: compiler.err.cant.apply.symbol: kindname.method, call, TargetType39.SAM, @442, kindname.class, TargetType39, (compiler.misc.cyclic.inference: U) -TargetType39.java:20:9: compiler.err.cant.apply.symbol: kindname.method, call, TargetType39.SAM, @479, kindname.class, TargetType39, (compiler.misc.cyclic.inference: V) +TargetType39.java:19:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: U) +TargetType39.java:20:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: V) 2 errors diff --git a/langtools/test/tools/javac/lambda/TargetType43.out b/langtools/test/tools/javac/lambda/TargetType43.out index b7b8766c516..7d50949d9a0 100644 --- a/langtools/test/tools/javac/lambda/TargetType43.out +++ b/langtools/test/tools/javac/lambda/TargetType43.out @@ -1,5 +1,5 @@ -TargetType43.java:13:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +TargetType43.java:13:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) TargetType43.java:13:30: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, TargetType43, null) -TargetType43.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Object, @359, kindname.class, TargetType43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf)) +TargetType43.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Object, @359, kindname.class, TargetType43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: java.lang.Object)) TargetType43.java:14:21: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, TargetType43, null) 4 errors diff --git a/langtools/test/tools/javac/lambda/TargetType45.java b/langtools/test/tools/javac/lambda/TargetType45.java index be38d176473..3d1e6f83ee6 100644 --- a/langtools/test/tools/javac/lambda/TargetType45.java +++ b/langtools/test/tools/javac/lambda/TargetType45.java @@ -3,7 +3,7 @@ * @bug 8003280 * @summary Add lambda tests * compiler crashes during flow analysis as it fails to report diagnostics during attribution - * @compile/fail/ref=TargetType45.out -XDrawDiagnostics TargetType45.java + * @compile TargetType45.java */ class TargetType45 { diff --git a/langtools/test/tools/javac/lambda/TargetType45.out b/langtools/test/tools/javac/lambda/TargetType45.out deleted file mode 100644 index 062dd71710d..00000000000 --- a/langtools/test/tools/javac/lambda/TargetType45.out +++ /dev/null @@ -1,2 +0,0 @@ -TargetType45.java:27:28: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.inconvertible.types: TargetType45.Mapper, TargetType45.Mapper)) -1 error diff --git a/langtools/test/tools/javac/lambda/TargetType50.out b/langtools/test/tools/javac/lambda/TargetType50.out index 14ec13ba3e4..02736d43b46 100644 --- a/langtools/test/tools/javac/lambda/TargetType50.out +++ b/langtools/test/tools/javac/lambda/TargetType50.out @@ -1,3 +1,3 @@ -TargetType50.java:25:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.String, java.lang.String,java.lang.Object) -TargetType50.java:26:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.String, java.lang.String,java.lang.Object) +TargetType50.java:25:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: TargetType50.Sink, TargetType50.Sink) +TargetType50.java:26:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: TargetType50.Sink, TargetType50.Sink) 2 errors diff --git a/langtools/test/tools/javac/lambda/TargetType51.java b/langtools/test/tools/javac/lambda/TargetType51.java new file mode 100644 index 00000000000..a26a9af0053 --- /dev/null +++ b/langtools/test/tools/javac/lambda/TargetType51.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary smoke test for combinator-like stuck analysis + * @author Maurizio Cimadamore + * @compile TargetType51.java + */ + +import java.util.Comparator; + +class TargetType51 { + + interface SimpleMapper { + T map(U t); + } + + interface SimpleList { + SimpleList sort(Comparator c); + } + + static class Person { + String getName() { return ""; } + } + + > Comparator comparing(SimpleMapper mapper) { return null; } + + static class F, T> { + F(SimpleMapper f) { } + } + + void testAssignmentContext(SimpleList list, boolean cond) { + SimpleList p1 = list.sort(comparing(Person::getName)); + SimpleList p2 = list.sort(comparing(x->x.getName())); + SimpleList p3 = list.sort(cond ? comparing(Person::getName) : comparing(x->x.getName())); + SimpleList p4 = list.sort((cond ? comparing(Person::getName) : comparing(x->x.getName()))); + } + + void testMethodContext(SimpleList list, boolean cond) { + testMethodContext(list.sort(comparing(Person::getName)), true); + testMethodContext(list.sort(comparing(x->x.getName())), true); + testMethodContext(list.sort(cond ? comparing(Person::getName) : comparing(x->x.getName())), true); + testMethodContext(list.sort((cond ? comparing(Person::getName) : comparing(x->x.getName()))), true); + } +} diff --git a/langtools/test/tools/javac/lambda/TargetType52.java b/langtools/test/tools/javac/lambda/TargetType52.java new file mode 100644 index 00000000000..752ff405bb9 --- /dev/null +++ b/langtools/test/tools/javac/lambda/TargetType52.java @@ -0,0 +1,17 @@ +/* + * @test /nodynamiccopyright/ + * @summary uncatched sam conversion failure exception lead to javac crash + * @compile/fail/ref=TargetType52.out -XDrawDiagnostics TargetType52.java + */ +class TargetType52 { + + interface FI> { + T m(V p); + } + + void m(FI> fip) { } + + void test() { + m(p -> p.get(0)); + } +} diff --git a/langtools/test/tools/javac/lambda/TargetType52.out b/langtools/test/tools/javac/lambda/TargetType52.out new file mode 100644 index 00000000000..962bbb79ded --- /dev/null +++ b/langtools/test/tools/javac/lambda/TargetType52.out @@ -0,0 +1,2 @@ +TargetType52.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m, TargetType52.FI>, @444, kindname.class, TargetType52, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: TargetType52.FI>)) +1 error diff --git a/langtools/test/tools/javac/lambda/TestInvokeDynamic.java b/langtools/test/tools/javac/lambda/TestInvokeDynamic.java index e6f7830797e..3b38d73c44d 100644 --- a/langtools/test/tools/javac/lambda/TestInvokeDynamic.java +++ b/langtools/test/tools/javac/lambda/TestInvokeDynamic.java @@ -24,15 +24,18 @@ /* * @test * @bug 7194586 - * - * @bug 8003280 + * @bug 8003280 8006694 * @summary Add lambda tests * Add back-end support for invokedynamic + * temporarily workaround combo tests are causing time out in several platforms * @library ../lib * @build JavacTestingAbstractThreadedTest - * @run main TestInvokeDynamic + * @run main/othervm TestInvokeDynamic */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import com.sun.source.tree.MethodInvocationTree; import com.sun.source.tree.MethodTree; import com.sun.source.util.TaskEvent; @@ -48,7 +51,6 @@ import com.sun.tools.classfile.Instruction; import com.sun.tools.classfile.Method; import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symtab; @@ -67,11 +69,8 @@ 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.StandardJavaFileManager; -import javax.tools.ToolProvider; import static com.sun.tools.javac.jvm.ClassFile.*; diff --git a/langtools/test/tools/javac/lambda/VoidCompatibility.java b/langtools/test/tools/javac/lambda/VoidCompatibility.java index 90205da7f79..41fcf487e8e 100644 --- a/langtools/test/tools/javac/lambda/VoidCompatibility.java +++ b/langtools/test/tools/javac/lambda/VoidCompatibility.java @@ -3,7 +3,7 @@ * @bug 8003280 * @summary Add lambda tests * check that that void compatibility affects overloading as expected - * @compile/fail/ref=VoidCompatibility.out -XDrawDiagnostics VoidCompatibility.java + * @compile VoidCompatibility.java */ class VoidCompatibility { @@ -14,13 +14,13 @@ class VoidCompatibility { void schedule(Thunk t) { } void test() { - schedule(() -> System.setProperty("done", "true")); //2 + schedule(() -> System.setProperty("done", "true")); //non-void most specific schedule(() -> { System.setProperty("done", "true"); }); //1 schedule(() -> { return System.setProperty("done", "true"); }); //2 schedule(() -> System.out.println("done")); //1 schedule(() -> { System.out.println("done"); }); //1 schedule(Thread::yield); //1 - schedule(Thread::getAllStackTraces); //ambiguous + schedule(Thread::getAllStackTraces); //non-void most specific schedule(Thread::interrupted); //1 (most specific) } } diff --git a/langtools/test/tools/javac/lambda/VoidCompatibility.out b/langtools/test/tools/javac/lambda/VoidCompatibility.out deleted file mode 100644 index 0d3a8e809b9..00000000000 --- a/langtools/test/tools/javac/lambda/VoidCompatibility.out +++ /dev/null @@ -1,3 +0,0 @@ -VoidCompatibility.java:17:9: compiler.err.ref.ambiguous: schedule, kindname.method, schedule(VoidCompatibility.Runnable), VoidCompatibility, kindname.method, schedule(VoidCompatibility.Thunk), VoidCompatibility -VoidCompatibility.java:23:9: compiler.err.ref.ambiguous: schedule, kindname.method, schedule(VoidCompatibility.Runnable), VoidCompatibility, kindname.method, schedule(VoidCompatibility.Thunk), VoidCompatibility -2 errors diff --git a/langtools/test/tools/javac/lambda/WarnUnderscoreAsIdent.java b/langtools/test/tools/javac/lambda/WarnUnderscoreAsIdent.java new file mode 100644 index 00000000000..2090e4b4375 --- /dev/null +++ b/langtools/test/tools/javac/lambda/WarnUnderscoreAsIdent.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @summary Check usages of underscore as identifier generate warnings + * @compile/fail/ref=WarnUnderscoreAsIdent.out -XDrawDiagnostics -Werror WarnUnderscoreAsIdent.java + */ +package _._; + +import _._; + +class _ { + String _ = null; + void _(String _) { } + void testLocal() { + String _ = null; + } + void testFor() { + for (int _ = 0; _ < 10; _++); + } + void testTry() { + try { } catch (Throwable _) { } + } + void testLabel() { + _: + for (;;) { + break _; + } + _: + for (;;) { + continue _; + } + } +} diff --git a/langtools/test/tools/javac/lambda/WarnUnderscoreAsIdent.out b/langtools/test/tools/javac/lambda/WarnUnderscoreAsIdent.out new file mode 100644 index 00000000000..0d1185ff0dc --- /dev/null +++ b/langtools/test/tools/javac/lambda/WarnUnderscoreAsIdent.out @@ -0,0 +1,20 @@ +WarnUnderscoreAsIdent.java:29:9: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:29:11: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:31:8: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:31:10: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:33:7: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:34:12: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:35:10: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:35:19: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:37:16: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:40:18: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:40:25: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:40:33: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:43:34: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:46:9: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:48:19: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:50:9: compiler.warn.underscore.as.identifier +WarnUnderscoreAsIdent.java:52:22: compiler.warn.underscore.as.identifier +- compiler.err.warnings.and.werror +1 error +17 warnings diff --git a/langtools/test/tools/javac/lambda/funcInterfaces/LambdaTest2_neg1.out b/langtools/test/tools/javac/lambda/funcInterfaces/LambdaTest2_neg1.out index 4780e80fec6..0a96b7ded8d 100644 --- a/langtools/test/tools/javac/lambda/funcInterfaces/LambdaTest2_neg1.out +++ b/langtools/test/tools/javac/lambda/funcInterfaces/LambdaTest2_neg1.out @@ -1,2 +1,2 @@ -LambdaTest2_neg1.java:15:13: compiler.err.cant.apply.symbol: kindname.method, methodQooRoo, QooRoo, @531, kindname.class, LambdaTest2_neg1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, QooRoo))) +LambdaTest2_neg1.java:15:13: compiler.err.cant.apply.symbol: kindname.method, methodQooRoo, QooRoo, @531, kindname.class, LambdaTest2_neg1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf.1: QooRoo, (compiler.misc.incompatible.abstracts: kindname.interface, QooRoo))) 1 error diff --git a/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM1.out b/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM1.out index c2472263c0a..abfaf967caa 100644 --- a/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM1.out +++ b/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM1.out @@ -1,2 +1,2 @@ -NonSAM1.java:11:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, Planet)) +NonSAM1.java:11:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: Planet, (compiler.misc.no.abstracts: kindname.interface, Planet)) 1 error diff --git a/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM3.out b/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM3.out index 8c9ff08b5ae..9f52ba5f767 100644 --- a/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM3.out +++ b/langtools/test/tools/javac/lambda/funcInterfaces/NonSAM3.out @@ -1,9 +1,9 @@ -NonSAM3.java:15:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, FooBar)) -NonSAM3.java:16:22: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, FooBar)) -NonSAM3.java:17:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:18:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:19:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:20:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:21:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) -NonSAM3.java:22:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:15:21: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: FooBar, (compiler.misc.incompatible.abstracts: kindname.interface, FooBar)) +NonSAM3.java:16:22: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: FooBar, (compiler.misc.incompatible.abstracts: kindname.interface, FooBar)) +NonSAM3.java:17:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:18:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:19:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:20:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:21:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) +NonSAM3.java:22:18: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: DE, (compiler.misc.incompatible.abstracts: kindname.interface, DE)) 8 errors diff --git a/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java index 560aae32e4a..45e75b74d75 100644 --- a/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java +++ b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java @@ -248,7 +248,7 @@ public class IntersectionTargetTypeTest { void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, - Arrays.asList("-XDallowIntersectionTypes"), null, Arrays.asList(source)); + null, null, Arrays.asList(source)); try { ct.analyze(); } catch (Throwable ex) { diff --git a/langtools/test/tools/javac/lambda/lambdaExpression/AbstractClass_neg.out b/langtools/test/tools/javac/lambda/lambdaExpression/AbstractClass_neg.out index 2fc5555b1e6..cfe68383937 100644 --- a/langtools/test/tools/javac/lambda/lambdaExpression/AbstractClass_neg.out +++ b/langtools/test/tools/javac/lambda/lambdaExpression/AbstractClass_neg.out @@ -1,2 +1,2 @@ -AbstractClass_neg.java:16:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +AbstractClass_neg.java:16:17: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: AbstractClass_neg.SAM) 1 error diff --git a/langtools/test/tools/javac/lambda/lambdaExpression/InvalidExpression5.out b/langtools/test/tools/javac/lambda/lambdaExpression/InvalidExpression5.out index 251425e6675..f9c70cddcb8 100644 --- a/langtools/test/tools/javac/lambda/lambdaExpression/InvalidExpression5.out +++ b/langtools/test/tools/javac/lambda/lambdaExpression/InvalidExpression5.out @@ -1,2 +1,2 @@ -InvalidExpression5.java:12:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf) +InvalidExpression5.java:12:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) 1 error diff --git a/langtools/test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java b/langtools/test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java index b64ca3df279..baf359bcaf1 100644 --- a/langtools/test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java +++ b/langtools/test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java @@ -149,8 +149,7 @@ public class SamConversionComboTest { return false; //ambiguous target type } else if(lambdaBody == LambdaBody.IMPLICIT) { - if(returnValue != ReturnValue.INTEGER) //ambiguous target type - return false; + return false; } else { //explicit parameter type if(fInterface.getParameterType().equals("Integer")) //ambiguous target type diff --git a/langtools/test/tools/javac/lambda/methodReference/SamConversion.java b/langtools/test/tools/javac/lambda/methodReference/SamConversion.java index afe24fb7bd4..134973ae236 100644 --- a/langtools/test/tools/javac/lambda/methodReference/SamConversion.java +++ b/langtools/test/tools/javac/lambda/methodReference/SamConversion.java @@ -149,14 +149,6 @@ public class SamConversion { test2(A::method3, 4); test2(new A()::method4, 5); test2(new A()::method5, 6); - A a = new A(A::method1); //A(Foo f) called - assertTrue(a.method2(1) == 11); - assertTrue(a.method4(1) == 11); - assertTrue(a.method5(1) == 11); - A a2 = new A(new A()::method2); //A(Bar b) called - assertTrue(a2.method2(1) == 12); - assertTrue(a2.method4(1) == 12); - assertTrue(a2.method5(1) == 12); } /** @@ -279,7 +271,7 @@ public class SamConversion { testConditionalExpression(false); testLambdaExpressionBody(); - assertTrue(assertionCount == 38); + assertTrue(assertionCount == 32); } static class MyException extends Exception {} diff --git a/langtools/test/tools/javac/lambda/methodReference/SamConversionComboTest.java b/langtools/test/tools/javac/lambda/methodReference/SamConversionComboTest.java index d705cdc38fd..22d8e25df73 100644 --- a/langtools/test/tools/javac/lambda/methodReference/SamConversionComboTest.java +++ b/langtools/test/tools/javac/lambda/methodReference/SamConversionComboTest.java @@ -186,10 +186,7 @@ public class SamConversionComboTest { if(context != Context.CONSTRUCTOR && fInterface != FInterface.C && methodDef == MethodDef.METHOD6) //method that throws exceptions not thrown by the interface method is a mismatch return false; - if(context == Context.CONSTRUCTOR && - methodReference != MethodReference.METHOD1 && - methodReference != MethodReference.METHOD2 && - methodReference != MethodReference.METHOD3)//ambiguous reference + if(context == Context.CONSTRUCTOR) return false; return true; } diff --git a/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java b/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java index b32bfc1a95c..dbd7d1366a0 100644 --- a/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java +++ b/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java @@ -23,14 +23,18 @@ /* * @test - * @bug 8003280 + * @bug 8003280 8006694 * @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 * @build JavacTestingAbstractThreadedTest - * @run main/timeout=600 StructuralMostSpecificTest + * @run main/othervm/timeout=600 StructuralMostSpecificTest */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import javax.tools.Diagnostic; diff --git a/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out b/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out index 83b93f0e098..7f647251ecf 100644 --- a/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out +++ b/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out @@ -1,2 +1,2 @@ -InferenceTest_neg5.java:14:13: compiler.err.cant.apply.symbol: kindname.method, method1, InferenceTest_neg5.SAM1, @419, kindname.class, InferenceTest_neg5, (compiler.misc.cyclic.inference: X) +InferenceTest_neg5.java:14:21: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: X) 1 error diff --git a/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java b/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java index 1d24a294e98..9399eb7b284 100644 --- a/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java +++ b/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java @@ -23,16 +23,20 @@ /** * @test - * @bug 8003280 + * @bug 8003280 8006694 * @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 * @build JavacTestingAbstractThreadedTest * @compile TypeInferenceComboTest.java - * @run main/timeout=360 TypeInferenceComboTest + * @run main/othervm/timeout=360 TypeInferenceComboTest */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import javax.tools.Diagnostic; @@ -256,16 +260,6 @@ public class TypeInferenceComboTest }; public void run() { - outWriter.println("kk:"); - StringBuilder sb = new StringBuilder("SamKind:"); - sb.append(samKind).append(" SamTargetType:") - .append(samTargetType).append(" ParameterType:").append(parameterType) - .append(" ReturnType:").append(returnType).append(" Context:") - .append(context).append(" LambdaKind:").append(lambdaKind) - .append(" LambdaBodyType:").append(lambdaBodyType) - .append(" ParameterKind:").append(parameterKind).append(" Keyword:") - .append(keyword); - outWriter.println(sb); DiagnosticChecker dc = new DiagnosticChecker(); JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc, null, null, Arrays.asList(samSourceFile, clientSourceFile)); diff --git a/langtools/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java b/langtools/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java index 1c245ea9b76..646a1c95d42 100644 --- a/langtools/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java +++ b/langtools/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java @@ -807,20 +807,8 @@ public class DefaultMethodsTest extends TestHarness { fail("Could not load class", e); } } - - public void testSynchronizedDefault() { - try { - java.lang.Class.forName("org.openjdk.tests.vm.SynchronizedDefault"); - } catch (Exception e) { - fail("Could not load class", e); - } - } } interface StrictfpDefault { default strictfp void m() {} } - -interface SynchronizedDefault { - default synchronized void m() {} -} diff --git a/langtools/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/FDSeparateCompilationTest.java b/langtools/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/FDSeparateCompilationTest.java index 5cb864492d5..9626b45edea 100644 --- a/langtools/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/FDSeparateCompilationTest.java +++ b/langtools/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/FDSeparateCompilationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -23,6 +23,9 @@ * questions. */ +// this test has been disabled because of timeout issues. +// see JDK-8006746 + package org.openjdk.tests.vm; import java.util.*; @@ -91,7 +94,7 @@ public class FDSeparateCompilationTest extends TestHarness { private static final ConcreteMethod canonicalMethod = new ConcreteMethod( "String", "m", "returns " + EMPTY + ";", AccessFlag.PUBLIC); - @Test(groups = "vm", dataProvider = "allShapes") + @Test(enabled = false, groups = "vm", dataProvider = "allShapes") public void separateCompilationTest(Hierarchy hs) { ClassCase cc = hs.root; Type type = sourceTypeFrom(hs.root); diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java new file mode 100644 index 00000000000..45d1296cdda --- /dev/null +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -0,0 +1,1331 @@ +/* + * Copyright (c) 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.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.tools.FileObject; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTrees; +import com.sun.tools.javac.code.Annotations; +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Printer; +import com.sun.tools.javac.code.Scope; +import com.sun.tools.javac.code.Scope.CompoundScope; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.code.TypeTag; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.Pretty; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Log; + + +/** + * Debug printer for javac internals, for when toString() just isn't enough. + * + *

                                + * The printer provides an API to generate structured views of javac objects, + * such as AST nodes, symbol, types and annotations. Various aspects of the + * output can be configured, such as whether to show nulls, empty lists, or + * a compressed representation of the source code. Visitors are used to walk + * object hierarchies, and can be replaced with custom visitors if the default + * visitors are not flexible enough. + * + *

                                + * In general, nodes are printed with an initial line identifying the node + * followed by indented lines for the child nodes. Currently, graphs are + * represented by printing a spanning subtree. + * + *

                                + * The printer can be accessed via a simple command-line utility, + * which makes it easy to see the internal representation of source code, + * such as simple test programs, during the compilation pipeline. + * + *

                                This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + +public class DPrinter { + protected final PrintWriter out; + protected final Trees trees; + protected Printer printer; + protected boolean showEmptyItems = true; + protected boolean showNulls = true; + protected boolean showPositions = false; + protected boolean showSrc; + protected boolean showTreeSymbols; + protected boolean showTreeTypes; + protected int maxSrcLength = 32; + protected Locale locale = Locale.getDefault(); + protected static final String NULL = "#null"; + + // + + public static DPrinter instance(Context context) { + DPrinter dp = context.get(DPrinter.class); + if (dp == null) { + dp = new DPrinter(context); + } + return dp; + + } + + protected DPrinter(Context context) { + context.put(DPrinter.class, this); + out = context.get(Log.outKey); + trees = JavacTrees.instance(context); + } + + public DPrinter(PrintWriter out, Trees trees) { + this.out = out; + this.trees = trees; + } + + public DPrinter emptyItems(boolean showEmptyItems) { + this.showEmptyItems = showEmptyItems; + return this; + } + + public DPrinter nulls(boolean showNulls) { + this.showNulls = showNulls; + return this; + } + + public DPrinter positions(boolean showPositions) { + this.showPositions = showPositions; + return this; + } + + public DPrinter source(boolean showSrc) { + this.showSrc = showSrc; + return this; + } + + public DPrinter source(int maxSrcLength) { + this.showSrc = true; + this.maxSrcLength = maxSrcLength; + return this; + } + + public DPrinter treeSymbols(boolean showTreeSymbols) { + this.showTreeSymbols = showTreeSymbols; + return this; + } + + public DPrinter treeTypes(boolean showTreeTypes) { + this.showTreeTypes = showTreeTypes; + return this; + } + + public DPrinter typeSymbolPrinter(Printer p) { + printer = p; + return this; + } + + // + + // + + protected enum Details { + /** A one-line non-recursive summary */ + SUMMARY, + /** Multi-line, possibly recursive. */ + FULL + }; + + public void printAnnotations(String label, Annotations annotations) { + printAnnotations(label, annotations, Details.FULL); + } + + protected void printAnnotations(String label, Annotations annotations, Details details) { + if (annotations == null) { + printNull(label); + } else { + // no SUMMARY format currently available to use + + // use reflection to get at private fields + Object DECL_NOT_STARTED = getField(null, Annotations.class, "DECL_NOT_STARTED"); + Object DECL_IN_PROGRESS = getField(null, Annotations.class, "DECL_IN_PROGRESS"); + Object attributes = getField(annotations, Annotations.class, "attributes"); + Object type_attributes = getField(annotations, Annotations.class, "type_attributes"); + + if (!showEmptyItems) { + if (attributes instanceof List && ((List) attributes).isEmpty() + && attributes != DECL_NOT_STARTED + && attributes != DECL_IN_PROGRESS + && type_attributes instanceof List && ((List) type_attributes).isEmpty()) + return; + } + + printString(label, hashString(annotations)); + + indent(+1); + if (attributes == DECL_NOT_STARTED) + printString("attributes", "DECL_NOT_STARTED"); + else if (attributes == DECL_IN_PROGRESS) + printString("attributes", "DECL_IN_PROGRESS"); + else if (attributes instanceof List) + printList("attributes", (List) attributes); + else + printObject("attributes", attributes, Details.SUMMARY); + + if (attributes instanceof List) + printList("type_attributes", (List) type_attributes); + else + printObject("type_attributes", type_attributes, Details.SUMMARY); + indent(-1); + } + } + + public void printAttribute(String label, Attribute attr) { + if (attr == null) { + printNull(label); + } else { + printString(label, attr.getClass().getSimpleName()); + + indent(+1); + attr.accept(attrVisitor); + indent(-1); + } + } + + public void printFileObject(String label, FileObject fo) { + if (fo == null) { + printNull(label); + } else { + printString(label, fo.getName()); + } + } + + protected void printImplClass(T item, Class stdImplClass) { + if (item.getClass() != stdImplClass) + printString("impl", item.getClass().getName()); + } + + public void printInt(String label, int i) { + printString(label, String.valueOf(i)); + } + + public void printList(String label, List list) { + if (list == null) { + printNull(label); + } else if (!list.isEmpty() || showEmptyItems) { + printString(label, "[" + list.size() + "]"); + + indent(+1); + int i = 0; + for (Object item: list) { + printObject(String.valueOf(i++), item, Details.FULL); + } + indent(-1); + } + } + + public void printName(String label, Name name) { + if (name == null) { + printNull(label); + } else { + printString(label, name.toString()); + } + } + + public void printNull(String label) { + if (showNulls) + printString(label, NULL); + } + + protected void printObject(String label, Object item, Details details) { + if (item == null) { + printNull(label); + } else if (item instanceof Attribute) { + printAttribute(label, (Attribute) item); + } else if (item instanceof Symbol) { + printSymbol(label, (Symbol) item, details); + } else if (item instanceof Type) { + printType(label, (Type) item, details); + } else if (item instanceof JCTree) { + printTree(label, (JCTree) item); + } else if (item instanceof List) { + printList(label, (List) item); + } else if (item instanceof Name) { + printName(label, (Name) item); + } else { + printString(label, String.valueOf(item)); + } + } + + public void printScope(String label, Scope scope) { + printScope(label, scope, Details.FULL); + } + + public void printScope(String label, Scope scope, Details details) { + if (scope == null) { + printNull(label); + } else { + switch (details) { + case SUMMARY: { + indent(); + out.print(label); + out.print(": ["); + String sep = ""; + for (Symbol sym: scope.getElements()) { + out.print(sep); + out.print(sym.name); + sep = ","; + } + out.println("]"); + break; + } + + case FULL: { + indent(); + out.println(label); + + indent(+1); + printImplClass(scope, Scope.class); + printSymbol("owner", scope.owner, Details.SUMMARY); + printScope("next", scope.next, Details.SUMMARY); + printObject("shared", getField(scope, Scope.class, "shared"), Details.SUMMARY); + if (scope instanceof CompoundScope) { + printObject("subScopes", + getField(scope, CompoundScope.class, "subScopes"), + Details.FULL); + } else { + for (Symbol sym : scope.getElements()) { + printSymbol(sym.name.toString(), sym, Details.SUMMARY); + } + } + indent(-1); + break; + } + } + } + } + + public void printSource(String label, JCTree tree) { + printString(label, Pretty.toSimpleString(tree, maxSrcLength)); + } + + public void printString(String label, String text) { + indent(); + out.print(label); + out.print(": "); + out.print(text); + out.println(); + } + + public void printSymbol(String label, Symbol symbol) { + printSymbol(label, symbol, Details.FULL); + } + + protected void printSymbol(String label, Symbol sym, Details details) { + if (sym == null) { + printNull(label); + } else { + switch (details) { + case SUMMARY: + printString(label, toString(sym)); + break; + + case FULL: + indent(); + out.print(label); + out.println(": " + + info(sym.getClass(), + String.format("0x%x--%s", sym.kind, Kinds.kindName(sym)), + sym.getKind()) + + " " + sym.name + + " " + hashString(sym)); + + indent(+1); + if (showSrc) { + JCTree tree = (JCTree) trees.getTree(sym); + if (tree != null) + printSource("src", tree); + } + printString("flags", String.format("0x%x--%s", + sym.flags_field, Flags.toString(sym.flags_field))); + printObject("completer", sym.completer, Details.SUMMARY); // what if too long? + printSymbol("owner", sym.owner, Details.SUMMARY); + printType("type", sym.type, Details.SUMMARY); + printType("erasure", sym.erasure_field, Details.SUMMARY); + sym.accept(symVisitor, null); + printAnnotations("annotations", sym.annotations, Details.SUMMARY); + indent(-1); + } + } + } + + protected String toString(Symbol sym) { + return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym); + } + + protected void printTree(String label, JCTree tree) { + if (tree == null) { + printNull(label); + } else { + indent(); + String ext; + try { + ext = tree.getKind().name(); + } catch (Throwable t) { + ext = "n/a"; + } + out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext)); + if (showPositions) { + // We can always get start position, but to get end position + // and/or line+offset, we would need a JCCompilationUnit + out.print(" pos:" + tree.pos); + } + if (showTreeTypes && tree.type != null) + out.print(" type:" + toString(tree.type)); + Symbol sym; + if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null) + out.print(" sym:" + toString(sym)); + out.println(); + + indent(+1); + if (showSrc) { + indent(); + out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength)); + } + tree.accept(treeVisitor); + indent(-1); + } + } + + public void printType(String label, Type type) { + printType(label, type, Details.FULL); + } + + protected void printType(String label, Type type, Details details) { + if (type == null) + printNull(label); + else { + switch (details) { + case SUMMARY: + printString(label, toString(type)); + break; + + case FULL: + indent(); + out.print(label); + out.println(": " + info(type.getClass(), type.getTag(), type.getKind()) + + " " + hashString(type)); + + indent(+1); + printSymbol("tsym", type.tsym, Details.SUMMARY); + printObject("constValue", type.constValue(), Details.SUMMARY); + type.accept(typeVisitor, null); + indent(-1); + } + } + } + + protected String toString(Type type) { + return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); + } + + protected String hashString(Object obj) { + return String.format("#%x", obj.hashCode()); + } + + protected String info(Class clazz, Object internal, Object external) { + return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external); + } + + private int indent = 0; + + protected void indent() { + for (int i = 0; i < indent; i++) { + out.print(" "); + } + } + + protected void indent(int n) { + indent += n; + } + + protected Object getField(Object o, Class clazz, String name) { + try { + Field f = clazz.getDeclaredField(name); + boolean prev = f.isAccessible(); + f.setAccessible(true); + try { + return f.get(o); + } finally { + f.setAccessible(prev); + } + } catch (ReflectiveOperationException e) { + return e; + } catch (SecurityException e) { + return e; + } + } + + // + + // + + protected JCTree.Visitor treeVisitor = new TreeVisitor(); + + /** + * Default visitor class for JCTree (AST) objects. + */ + public class TreeVisitor extends JCTree.Visitor { + @Override + public void visitTopLevel(JCCompilationUnit tree) { + printList("packageAnnotations", tree.packageAnnotations); + printTree("pid", tree.pid); + printList("defs", tree.defs); + } + + @Override + public void visitImport(JCImport tree) { + printTree("qualid", tree.qualid); + } + + @Override + public void visitClassDef(JCClassDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printList("typarams", tree.typarams); + printTree("extending", tree.extending); + printList("implementing", tree.implementing); + printList("defs", tree.defs); + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printTree("restype", tree.restype); + printList("typarams", tree.typarams); + printTree("recvparam", tree.recvparam); + printList("params", tree.params); + printList("thrown", tree.thrown); + printTree("defaultValue", tree.defaultValue); + printTree("body", tree.body); + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printTree("vartype", tree.vartype); + printTree("init", tree.init); + } + + @Override + public void visitSkip(JCSkip tree) { + } + + @Override + public void visitBlock(JCBlock tree) { + printList("stats", tree.stats); + } + + @Override + public void visitDoLoop(JCDoWhileLoop tree) { + printTree("body", tree.body); + printTree("cond", tree.cond); + } + + @Override + public void visitWhileLoop(JCWhileLoop tree) { + printTree("cond", tree.cond); + printTree("body", tree.body); + } + + @Override + public void visitForLoop(JCForLoop tree) { + printList("init", tree.init); + printTree("cond", tree.cond); + printList("step", tree.step); + printTree("body", tree.body); + } + + @Override + public void visitForeachLoop(JCEnhancedForLoop tree) { + printTree("var", tree.var); + printTree("expr", tree.expr); + printTree("body", tree.body); + } + + @Override + public void visitLabelled(JCLabeledStatement tree) { + printTree("body", tree.body); + } + + @Override + public void visitSwitch(JCSwitch tree) { + printTree("selector", tree.selector); + printList("cases", tree.cases); + } + + @Override + public void visitCase(JCCase tree) { + printTree("pat", tree.pat); + printList("stats", tree.stats); + } + + @Override + public void visitSynchronized(JCSynchronized tree) { + printTree("lock", tree.lock); + printTree("body", tree.body); + } + + @Override + public void visitTry(JCTry tree) { + printList("resources", tree.resources); + printTree("body", tree.body); + printList("catchers", tree.catchers); + printTree("finalizer", tree.finalizer); + } + + @Override + public void visitCatch(JCCatch tree) { + printTree("param", tree.param); + printTree("body", tree.body); + } + + @Override + public void visitConditional(JCConditional tree) { + printTree("cond", tree.cond); + printTree("truepart", tree.truepart); + printTree("falsepart", tree.falsepart); + } + + @Override + public void visitIf(JCIf tree) { + printTree("cond", tree.cond); + printTree("thenpart", tree.thenpart); + printTree("elsepart", tree.elsepart); + } + + @Override + public void visitExec(JCExpressionStatement tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitBreak(JCBreak tree) { + printName("label", tree.label); + } + + @Override + public void visitContinue(JCContinue tree) { + printName("label", tree.label); + } + + @Override + public void visitReturn(JCReturn tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitThrow(JCThrow tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitAssert(JCAssert tree) { + printTree("cond", tree.cond); + printTree("detail", tree.detail); + } + + @Override + public void visitApply(JCMethodInvocation tree) { + printList("typeargs", tree.typeargs); + printTree("meth", tree.meth); + printList("args", tree.args); + } + + @Override + public void visitNewClass(JCNewClass tree) { + printTree("encl", tree.encl); + printList("typeargs", tree.typeargs); + printTree("clazz", tree.clazz); + printList("args", tree.args); + printTree("def", tree.def); + } + + @Override + public void visitNewArray(JCNewArray tree) { + printList("annotations", tree.annotations); + printTree("elemtype", tree.elemtype); + printList("dims", tree.dims); + printList("dimAnnotations", tree.dimAnnotations); + printList("elems", tree.elems); + } + + @Override + public void visitLambda(JCLambda tree) { + printTree("body", tree.body); + printList("params", tree.params); + } + + @Override + public void visitParens(JCParens tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitAssign(JCAssign tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitAssignop(JCAssignOp tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitUnary(JCUnary tree) { + printTree("arg", tree.arg); + } + + @Override + public void visitBinary(JCBinary tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitTypeCast(JCTypeCast tree) { + printTree("clazz", tree.clazz); + printTree("expr", tree.expr); + } + + @Override + public void visitTypeTest(JCInstanceOf tree) { + printTree("expr", tree.expr); + printTree("clazz", tree.clazz); + } + + @Override + public void visitIndexed(JCArrayAccess tree) { + printTree("indexed", tree.indexed); + printTree("index", tree.index); + } + + @Override + public void visitSelect(JCFieldAccess tree) { + printTree("selected", tree.selected); + } + + @Override + public void visitReference(JCMemberReference tree) { + printTree("expr", tree.expr); + printList("typeargs", tree.typeargs); + } + + @Override + public void visitIdent(JCIdent tree) { + printName("name", tree.name); + } + + @Override + public void visitLiteral(JCLiteral tree) { + printString("value", Pretty.toSimpleString(tree, 32)); + } + + @Override + public void visitTypeIdent(JCPrimitiveTypeTree tree) { + printString("typetag", tree.typetag.name()); + } + + @Override + public void visitTypeArray(JCArrayTypeTree tree) { + printTree("elemtype", tree.elemtype); + } + + @Override + public void visitTypeApply(JCTypeApply tree) { + printTree("clazz", tree.clazz); + printList("arguments", tree.arguments); + } + + @Override + public void visitTypeUnion(JCTypeUnion tree) { + printList("alternatives", tree.alternatives); + } + + @Override + public void visitTypeIntersection(JCTypeIntersection tree) { + printList("bounds", tree.bounds); + } + + @Override + public void visitTypeParameter(JCTypeParameter tree) { + printName("name", tree.name); + printList("annotations", tree.annotations); + printList("bounds", tree.bounds); + } + + @Override + public void visitWildcard(JCWildcard tree) { + printTree("kind", tree.kind); + printTree("inner", tree.inner); + } + + @Override + public void visitTypeBoundKind(TypeBoundKind tree) { + printString("kind", tree.kind.name()); + } + + @Override + public void visitModifiers(JCModifiers tree) { + printList("annotations", tree.annotations); + printString("flags", String.valueOf(Flags.asFlagSet(tree.flags))); + } + + @Override + public void visitAnnotation(JCAnnotation tree) { + printTree("annotationType", tree.annotationType); + printList("args", tree.args); + } + + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + printList("annotations", tree.annotations); + printTree("underlyingType", tree.underlyingType); + } + + @Override + public void visitErroneous(JCErroneous tree) { + printList("errs", tree.errs); + } + + @Override + public void visitLetExpr(LetExpr tree) { + printList("defs", tree.defs); + printTree("expr", tree.expr); + } + + @Override + public void visitTree(JCTree tree) { + Assert.error(); + } + } + + // + + // + + protected Symbol.Visitor symVisitor = new SymbolVisitor(); + + /** + * Default visitor class for Symbol objects. + * Note: each visitXYZ method ends by calling the corresponding + * visit method for its superclass. + */ + class SymbolVisitor implements Symbol.Visitor { + @Override + public Void visitClassSymbol(ClassSymbol sym, Void ignore) { + printName("fullname", sym.fullname); + printName("flatname", sym.flatname); + printScope("members", sym.members_field); + printFileObject("sourcefile", sym.sourcefile); + printFileObject("classfile", sym.classfile); + // trans-local? + // pool? + return visitTypeSymbol(sym, null); + } + + @Override + public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { + // code + printList("params", sym.params); + printList("savedParameterNames", sym.savedParameterNames); + return visitSymbol(sym, null); + } + + @Override + public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { + printName("fullname", sym.fullname); + printScope("members", sym.members_field); + printSymbol("package-info", sym.package_info, Details.SUMMARY); + return visitTypeSymbol(sym, null); + } + + @Override + public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { + printInt("opcode", sym.opcode); + return visitMethodSymbol(sym, null); + } + + @Override + public Void visitVarSymbol(VarSymbol sym, Void ignore) { + printInt("pos", sym.pos); + printInt("adm", sym.adr); + // data is a private field, and the standard accessors may + // mutate it as part of lazy evaluation. Therefore, use + // reflection to get the raw data. + printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); + return visitSymbol(sym, null); + } + + @Override + public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { + return visitSymbol(sym, null); + } + + @Override + public Void visitSymbol(Symbol sym, Void ignore) { + return null; + } + } + + // + + // + + protected Type.Visitor typeVisitor = new TypeVisitor(); + + /** + * Default visitor class for Type objects. + * Note: each visitXYZ method ends by calling the corresponding + * visit method for its superclass. + */ + public class TypeVisitor implements Type.Visitor { + public Void visitAnnotatedType(AnnotatedType type, Void ignore) { + printList("typeAnnotations", type.typeAnnotations); + printType("underlyingType", type.underlyingType, Details.FULL); + return visitType(type, null); + } + + public Void visitArrayType(ArrayType type, Void ignore) { + printType("elemType", type.elemtype, Details.FULL); + return visitType(type, null); + } + + public Void visitCapturedType(CapturedType type, Void ignore) { + printType("wildcard", type.wildcard, Details.FULL); + return visitTypeVar(type, null); + } + + public Void visitClassType(ClassType type, Void ignore) { + printType("outer", type.getEnclosingType(), Details.SUMMARY); + printList("typarams", type.typarams_field); + printList("allparams", type.allparams_field); + printType("supertype", type.supertype_field, Details.SUMMARY); + printList("interfaces", type.interfaces_field); + printList("allinterfaces", type.all_interfaces_field); + return visitType(type, null); + } + + public Void visitErrorType(ErrorType type, Void ignore) { + printType("originalType", type.getOriginalType(), Details.FULL); + return visitClassType(type, null); + } + + public Void visitForAll(ForAll type, Void ignore) { + printList("tvars", type.tvars); + return visitDelegatedType(type); + } + + public Void visitMethodType(MethodType type, Void ignore) { + printList("argtypes", type.argtypes); + printType("restype", type.restype, Details.FULL); + printList("thrown", type.thrown); + return visitType(type, null); + } + + public Void visitPackageType(PackageType type, Void ignore) { + return visitType(type, null); + } + + public Void visitTypeVar(TypeVar type, Void ignore) { + // For TypeVars (and not subtypes), the bound should always be + // null or bot. So, only print the bound for subtypes of TypeVar, + // or if the bound is (erroneously) not null or bot. + if (!type.hasTag(TypeTag.TYPEVAR) + || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { + printType("bound", type.bound, Details.FULL); + } + printType("lower", type.lower, Details.FULL); + return visitType(type, null); + } + + public Void visitUndetVar(UndetVar type, Void ignore) { + for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) + printList("bounds." + ib, type.getBounds(ib)); + printType("inst", type.inst, Details.SUMMARY); + return visitDelegatedType(type); + } + + public Void visitWildcardType(WildcardType type, Void ignore) { + printType("type", type.type, Details.SUMMARY); + printString("kind", type.kind.name()); + printType("bound", type.bound, Details.SUMMARY); + return visitType(type, null); + } + + protected Void visitDelegatedType(DelegatedType type) { + printType("qtype", type.qtype, Details.FULL); + return visitType(type, null); + } + + public Void visitType(Type type, Void ignore) { + return null; + } + } + + // + + // + + protected Attribute.Visitor attrVisitor = new AttributeVisitor(); + + /** + * Default visitor class for Attribute (annotation) objects. + */ + public class AttributeVisitor implements Attribute.Visitor { + + public void visitConstant(Attribute.Constant a) { + printObject("value", a.value, Details.SUMMARY); + visitAttribute(a); + } + + public void visitClass(Attribute.Class a) { + printObject("classType", a.classType, Details.SUMMARY); + visitAttribute(a); + } + + public void visitCompound(Attribute.Compound a) { + if (a instanceof Attribute.TypeCompound) { + Attribute.TypeCompound ta = (Attribute.TypeCompound) a; + // consider a custom printer? + printObject("position", ta.position, Details.SUMMARY); + } + printObject("synthesized", a.isSynthesized(), Details.SUMMARY); + printList("values", a.values); + visitAttribute(a); + } + + public void visitArray(Attribute.Array a) { + printList("values", Arrays.asList(a.values)); + visitAttribute(a); + } + + public void visitEnum(Attribute.Enum a) { + printSymbol("value", a.value, Details.SUMMARY); + visitAttribute(a); + } + + public void visitError(Attribute.Error a) { + visitAttribute(a); + } + + public void visitAttribute(Attribute a) { + printType("type", a.type, Details.SUMMARY); + } + + } + // + + // + + /** + * Utility class to invoke DPrinter from the command line. + */ + static class Main { + public static void main(String... args) throws IOException { + Main m = new Main(); + PrintWriter out = new PrintWriter(System.out); + try { + if (args.length == 0) + m.usage(out); + else + m.run(out, args); + } finally { + out.flush(); + } + } + + void usage(PrintWriter out) { + out.println("Usage:"); + out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); + out.print("where mode is one of: "); + String sep = ""; + for (Handler h: getHandlers().values()) { + out.print(sep); + out.print(h.name); + sep = ", "; + } + out.println(); + out.println("and where options include:"); + out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); + out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); + out.println(" -showPositions"); + out.println(" -showSource"); + out.println(" -showTreeSymbols"); + out.println(" -showTreeTypes"); + out.println(" -hideEmptyItems"); + out.println(" -hideNulls"); + } + + void run(PrintWriter out, String... args) throws IOException { + JavaCompiler c = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); + + // DPrinter options + final Set before = EnumSet.noneOf(TaskEvent.Kind.class); + final Set after = EnumSet.noneOf(TaskEvent.Kind.class); + boolean showPositions = false; + boolean showSource = false; + boolean showTreeSymbols = false; + boolean showTreeTypes = false; + boolean showEmptyItems = true; + boolean showNulls = true; + + // javac options + Collection options = new ArrayList(); + Collection files = new ArrayList(); + String classpath = null; + String classoutdir = null; + + final Handler h = getHandlers().get(args[0]); + if (h == null) + throw new IllegalArgumentException(args[0]); + + for (int i = 1; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-before") && i + 1 < args.length) { + before.add(getKind(args[++i])); + } else if (arg.equals("-after") && i + 1 < args.length) { + after.add(getKind(args[++i])); + } else if (arg.equals("-showPositions")) { + showPositions = true; + } else if (arg.equals("-showSource")) { + showSource = true; + } else if (arg.equals("-showTreeSymbols")) { + showTreeSymbols = true; + } else if (arg.equals("-showTreeTypes")) { + showTreeTypes = true; + } else if (arg.equals("-hideEmptyLists")) { + showEmptyItems = false; + } else if (arg.equals("-hideNulls")) { + showNulls = false; + } else if (arg.equals("-classpath") && i + 1 < args.length) { + classpath = args[++i]; + } else if (arg.equals("-d") && i + 1 < args.length) { + classoutdir = args[++i]; + } else if (arg.startsWith("-")) { + int n = c.isSupportedOption(arg); + if (n < 0) throw new IllegalArgumentException(arg); + options.add(arg); + while (n > 0) options.add(args[++i]); + } else if (arg.endsWith(".java")) { + files.add(new File(arg)); + } + } + + if (classoutdir != null) { + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); + } + + if (classpath != null) { + Collection path = new ArrayList(); + for (String p: classpath.split(File.pathSeparator)) { + if (p.isEmpty()) continue; + File f = new File(p); + if (f.exists()) path.add(f); + } + fm.setLocation(StandardLocation.CLASS_PATH, path); + } + Iterable fos = fm.getJavaFileObjectsFromFiles(files); + + JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); + final Trees trees = Trees.instance(task); + + final DPrinter dprinter = new DPrinter(out, trees); + dprinter.source(showSource) + .emptyItems(showEmptyItems) + .nulls(showNulls) + .positions(showPositions) + .treeSymbols(showTreeSymbols) + .treeTypes(showTreeTypes); + + if (before.isEmpty() && after.isEmpty()) { + if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) + after.add(TaskEvent.Kind.PARSE); + else + after.add(TaskEvent.Kind.ANALYZE); + } + + task.addTaskListener(new TaskListener() { + public void started(TaskEvent e) { + if (before.contains(e.getKind())) + handle(e); + } + + public void finished(TaskEvent e) { + if (after.contains(e.getKind())) + handle(e); + } + + private void handle(TaskEvent e) { + switch (e.getKind()) { + case PARSE: + case ENTER: + h.handle(e.getSourceFile().getName(), + (JCTree) e.getCompilationUnit(), + dprinter); + break; + + default: + TypeElement elem = e.getTypeElement(); + h.handle(elem.toString(), + (JCTree) trees.getTree(elem), + dprinter); + break; + } + } + }); + + task.call(); + } + + TaskEvent.Kind getKind(String s) { + return TaskEvent.Kind.valueOf(s.toUpperCase()); + } + + static protected abstract class Handler { + final String name; + Handler(String name) { + this.name = name; + } + abstract void handle(String label, JCTree tree, DPrinter dprinter); + } + + Map getHandlers() { + Map map = new HashMap(); + for (Handler h: defaultHandlers) { + map.put(h.name, h); + } + return map; + } + + protected final Handler[] defaultHandlers = { + new Handler("trees") { + @Override + void handle(String name, JCTree tree, DPrinter dprinter) { + dprinter.printTree(name, tree); + dprinter.out.println(); + } + }, + + new Handler("symbols") { + @Override + void handle(String name, JCTree tree, final DPrinter dprinter) { + TreeScanner ds = new TreeScanner() { + @Override + public void visitClassDef(JCClassDecl tree) { + visitDecl(tree, tree.sym); + super.visitClassDef(tree); + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + visitDecl(tree, tree.sym); + super.visitMethodDef(tree); + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + visitDecl(tree, tree.sym); + super.visitVarDef(tree); + } + + void visitDecl(JCTree tree, Symbol sym) { + dprinter.printSymbol(sym.name.toString(), sym); + dprinter.out.println(); + } + }; + ds.scan(tree); + } + }, + + new Handler("types") { + @Override + void handle(String name, JCTree tree, final DPrinter dprinter) { + TreeScanner ts = new TreeScanner() { + @Override + public void scan(JCTree tree) { + if (tree == null) { + return; + } + if (tree.type != null) { + String label = Pretty.toSimpleString(tree); + dprinter.printType(label, tree.type); + dprinter.out.println(); + } + super.scan(tree); + } + }; + ts.scan(tree); + } + } + }; + } + + // + +} diff --git a/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java b/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java index b0b0b793d73..34029854351 100644 --- a/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java +++ b/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java @@ -26,6 +26,7 @@ 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; @@ -40,14 +41,20 @@ import javax.tools.ToolProvider; * * 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(); - return Math.max(2, Math.min(8, cores / 2)); + numberOfThreads.set(Math.max(2, Math.min(8, cores / 2))); + return numberOfThreads.get(); } protected static void checkAfterExec() throws InterruptedException { @@ -67,9 +74,7 @@ public abstract class JavacTestingAbstractThreadedTest { protected static void checkAfterExec(boolean printCheckCount) throws InterruptedException { pool.shutdown(); - while (!pool.isTerminated()) { - Thread.sleep(10); - } + pool.awaitTermination(15, TimeUnit.MINUTES); if (errCount.get() > 0) { if (throwAssertionOnError) { closePrinters(); @@ -83,11 +88,18 @@ public abstract class JavacTestingAbstractThreadedTest { } 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() { diff --git a/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java b/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java index 59c8419897a..a0c04263e30 100644 --- a/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java +++ b/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java @@ -23,13 +23,17 @@ /* * @test - * @bug 7030606 + * @bug 7030606 8006694 * @summary Project-coin: multi-catch types should be pairwise disjoint + * temporarily workaround combo tests are causing time out in several platforms * @library ../../lib * @build JavacTestingAbstractThreadedTest - * @run main DisjunctiveTypeWellFormednessTest + * @run main/othervm DisjunctiveTypeWellFormednessTest */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import javax.tools.Diagnostic; diff --git a/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out index 37632783d8f..5e68e1d9c15 100644 --- a/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out +++ b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out @@ -1,4 +1,3 @@ SemanticErrorTest.java:11:46: compiler.err.repeated.interface - compiler.err.proc.messager: Deliberate Error -SemanticErrorTest.java:11:46: compiler.err.repeated.interface -2 errors +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java index 33466e65476..13fe97c18af 100644 --- a/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java +++ b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -78,7 +78,7 @@ public class TestAnonClassNames { @Nesting(LOCAL) class LocalClass{}; - Object o = new /*@Nesting(ANONYMOUS)*/ Object() { // An anonymous annotated class + Object o = new @Nesting(ANONYMOUS) Object() { // An anonymous annotated class public String toString() { return "I have no name!"; } @@ -96,10 +96,9 @@ public class TestAnonClassNames { List names = new ArrayList(); for(Class clazz : classes) { String name = clazz.getName(); - Nesting anno = clazz.getAnnotation(Nesting.class); System.out.format("%s is %s%n", clazz.getName(), - anno == null ? "(unset/ANONYMOUS)" : anno.value()); + clazz.getAnnotation(Nesting.class).value()); testClassName(name); names.add(name); } @@ -158,6 +157,7 @@ public class TestAnonClassNames { } } +@Target({ElementType.TYPE, ElementType.TYPE_USE}) @Retention(RUNTIME) @interface Nesting { NestingKind value(); @@ -185,8 +185,8 @@ class ClassNameProber extends JavacTestingAbstractProcessor { typeElt.getQualifiedName().toString(), typeElt.getKind().toString(), nestingKind.toString()); - Nesting anno = typeElt.getAnnotation(Nesting.class); - if ((anno == null ? NestingKind.ANONYMOUS : anno.value()) != nestingKind) { + + if (typeElt.getAnnotation(Nesting.class).value() != nestingKind) { throw new RuntimeException("Mismatch of expected and reported nesting kind."); } } diff --git a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java index 70666856a21..2ddcd10bd26 100644 --- a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java +++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -28,7 +28,7 @@ * @summary Modeling type implementing missing interfaces * @library /tools/javac/lib * @build JavacTestingAbstractProcessor TestMissingElement - * @compile -proc:only -XprintRounds -processor TestMissingElement InvalidSource.java + * @compile/fail/ref=TestMissingElement.ref -proc:only -XprintRounds -XDrawDiagnostics -processor TestMissingElement InvalidSource.java */ import java.util.*; diff --git a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref new file mode 100644 index 00000000000..4c31a101dbb --- /dev/null +++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref @@ -0,0 +1,49 @@ +Round 1: + input files: {ExpectInterfaces, ExpectSupertype, OK, InvalidSource} + annotations: [ExpectSupertype, ExpectInterfaces] + last round: false +Round 2: + input files: {} + annotations: [] + last round: true +InvalidSource.java:55:42: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:58:44: compiler.err.doesnt.exist: A +InvalidSource.java:61:54: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.package, java.util, null) +InvalidSource.java:64:47: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:67:44: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:70:46: compiler.err.doesnt.exist: A +InvalidSource.java:73:55: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:76:59: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:79:46: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:79:49: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:82:44: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:85:46: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:88:50: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:91:45: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:91:48: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:94:49: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:97:51: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:97:57: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:100:49: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:103:51: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:103:57: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) +InvalidSource.java:106:58: compiler.err.cant.resolve.location: kindname.class, X, , , (compiler.misc.location: kindname.class, InvalidSource, null) +22 errors +check supertype: InvalidSource.TestClassMissingClassA -- !:empty clss A! +check supertype: InvalidSource.TestClassMissingClassAB -- !:empty clss (pkg A).B! +check supertype: InvalidSource.TestClassMissingClass_juA -- !:empty clss (pkg java.util).A! +check supertype: InvalidSource.TestClassTMissingClassAT -- !:empty clss A! +check interfaces: InvalidSource.TestClassMissingIntfA -- !:empty intf A! +check interfaces: InvalidSource.TestClassMissingIntfAB -- !:empty intf (pkg A).B! +check interfaces: InvalidSource.TestClassMissingIntfAOK -- !:empty intf A!, intf OK +check interfaces: InvalidSource.TestClassOKMissingIntfA -- intf OK, !:empty intf A! +check interfaces: InvalidSource.TestClassMissingIntfA_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestIntfMissingIntfA -- !:empty intf A! +check interfaces: InvalidSource.TestIntfMissingIntfAOK -- !:empty intf A!, intf OK +check interfaces: InvalidSource.TestIntfOKMissingIntfA -- intf OK, !:empty intf A! +check interfaces: InvalidSource.TestIntfMissingIntfAB -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestClassTMissingIntfAT -- !:empty intf A! +check interfaces: InvalidSource.TestClassTMissingIntfAT_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestIntfTMissingIntfAT -- !:empty intf A! +check interfaces: InvalidSource.TestIntfTMissingIntfAT_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestClassListMissingX -- intf (pkg java.util).List \ No newline at end of file diff --git a/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.java b/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.java index 78808318ba3..ee0b9039737 100644 --- a/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.java +++ b/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -28,7 +28,7 @@ * @author Scott Seligman * @library /tools/javac/lib * @build JavacTestingAbstractProcessor DirectSupersOfErr - * @compile -processor DirectSupersOfErr -proc:only C1.java + * @compile/fail/ref=DirectSupersOfErr.ref -processor DirectSupersOfErr -proc:only -XDrawDiagnostics C1.java */ import java.util.Set; diff --git a/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.ref b/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.ref new file mode 100644 index 00000000000..8fe9c7ed8be --- /dev/null +++ b/langtools/test/tools/javac/processing/model/util/directSupersOfErr/DirectSupersOfErr.ref @@ -0,0 +1,2 @@ +C1.java:24:18: compiler.err.cant.resolve: kindname.class, Bogus, , +1 error diff --git a/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java index 80ac69dd95d..7d2a2408892 100644 --- a/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java +++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java @@ -23,44 +23,44 @@ @TraceResolve(keys={"compiler.err.ref.ambiguous"}) class PrimitiveOverReferenceVarargsAmbiguous { - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS, mostSpecific=true) static void m_byte(byte... b) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS) static void m_byte(Byte... b) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS, mostSpecific=true) static void m_short(short... s) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS) static void m_short(Short... s) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS, mostSpecific=true) static void m_int(int... i) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS) static void m_int(Integer... i) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS, mostSpecific=true) static void m_long(long... l) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS) static void m_long(Long... l) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS, mostSpecific=true) static void m_float(float... f) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS) static void m_float(Float... f) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS, mostSpecific=true) static void m_double(double... d) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS) static void m_double(Double... d) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS, mostSpecific=true) static void m_char(char... c) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS) static void m_char(Character... c) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS, mostSpecific=true) static void m_bool(boolean... z) {} - @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + @Candidate(applicable=Phase.VARARGS) static void m_bool(Boolean... z) {} { diff --git a/langtools/test/tools/javac/tree/TreeKindTest.java b/langtools/test/tools/javac/tree/TreeKindTest.java index 608c45a4df7..8497308afb6 100644 --- a/langtools/test/tools/javac/tree/TreeKindTest.java +++ b/langtools/test/tools/javac/tree/TreeKindTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -29,7 +29,7 @@ import com.sun.source.tree.*; -public class TreeKindTest{ +public class TreeKindTest { public static void main(String... args) { boolean ok = true; @@ -108,6 +108,11 @@ public class TreeKindTest{ ok = ok & verify(k, i, i == ClassTree.class); break; + case ANNOTATION: + case TYPE_ANNOTATION: + ok = ok & verify(k, i, i == AnnotationTree.class); + break; + case OTHER: ok = ok & verify(k, i, i == null); break; diff --git a/langtools/test/tools/javac/tree/TreePosTest.java b/langtools/test/tools/javac/tree/TreePosTest.java index b8f8a36b1b0..8fed3e5c07f 100644 --- a/langtools/test/tools/javac/tree/TreePosTest.java +++ b/langtools/test/tools/javac/tree/TreePosTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -75,6 +75,7 @@ import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCAnnotatedType; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; @@ -100,7 +101,8 @@ import static com.sun.tools.javac.util.Position.NOPOS; * @test * @bug 6919889 * @summary assorted position errors in compiler syntax trees - * @run main TreePosTest -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations -et ANNOTATED_TYPE . + * OLD: -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations -et ANNOTATED_TYPE . + * @run main TreePosTest -q -r . */ public class TreePosTest { /** @@ -367,15 +369,24 @@ public class TreePosTest { // e.g. int[][] a = new int[2][]; check("encl.start <= start", encl, self, encl.start <= self.start); check("start <= pos", encl, self, self.start <= self.pos); - if (!(self.tag == TYPEARRAY + if (!( (self.tag == TYPEARRAY || + isAnnotatedArray(self.tree)) && (encl.tag == VARDEF || encl.tag == METHODDEF || - encl.tag == TYPEARRAY))) { + encl.tag == TYPEARRAY || + isAnnotatedArray(encl.tree)) + || + encl.tag == ANNOTATED_TYPE && self.tag == SELECT + )) { check("encl.pos <= start || end <= encl.pos", encl, self, encl.pos <= self.start || self.end <= encl.pos); } check("pos <= end", encl, self, self.pos <= self.end); - if (!(self.tag == TYPEARRAY && encl.tag == TYPEARRAY)) { + if (!( (self.tag == TYPEARRAY || isAnnotatedArray(self.tree)) && + (encl.tag == TYPEARRAY || isAnnotatedArray(encl.tree)) + || + encl.tag == MODIFIERS && self.tag == ANNOTATION + ) ) { check("end <= encl.end", encl, self, self.end <= encl.end); } } @@ -387,6 +398,11 @@ public class TreePosTest { encl = prevEncl; } + private boolean isAnnotatedArray(JCTree tree) { + return tree.hasTag(ANNOTATED_TYPE) && + ((JCAnnotatedType)tree).underlyingType.hasTag(TYPEARRAY); + } + @Override public void visitVarDef(JCVariableDecl tree) { // enum member declarations are desugared in the parser and have @@ -427,7 +443,8 @@ public class TreePosTest { viewer.addEntry(sourcefile, label, encl, self); } - String s = self.tree.toString(); + String s = "encl: " + encl.tree.toString() + + " this: " + self.tree.toString(); String msg = sourcefile.getName() + ": " + label + ": " + "encl:" + encl + " this:" + self + "\n" + s.substring(0, Math.min(80, s.length())).replaceAll("[\r\n]+", " "); diff --git a/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java b/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java new file mode 100644 index 00000000000..0db46b5774b --- /dev/null +++ b/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +/* + * @test + * @build DA TA Test TestProcessor + * @compile -proc:only -processor TestProcessor AnnoTreeTests.java + */ + +@Test(4) +class AnnoTreeTests { + // primitive types + // @TA("int") int i1 = 0; // TODO: Only visible via ClassFile + long i2 = (@TA("long") long) 0; + + // simple array types + // @DA("short") short[] a1; // TODO: Only visible via ClassFile + byte @TA("byte[]") [] a2; + float[] a3 = (@TA("float") float[]) null; + double[] a4 = (double @TA("double[]") []) null; + + // multi-dimensional array types + // (still to come) +} diff --git a/langtools/test/tools/javac/treeannotests/TestProcessor.java b/langtools/test/tools/javac/treeannotests/TestProcessor.java index f74cd3c7cea..8b6c4adb265 100644 --- a/langtools/test/tools/javac/treeannotests/TestProcessor.java +++ b/langtools/test/tools/javac/treeannotests/TestProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -203,13 +203,16 @@ public class TestProcessor extends AbstractProcessor { * expression name=value. */ String getStringValue(JCExpression e) { - if (e.getTag() == JCTree.ASSIGN) { + if (e.hasTag(JCTree.Tag.ASSIGN)) { JCAssign a = (JCAssign) e; JCExpression rhs = a.rhs; - if (rhs.getTag() == JCTree.LITERAL) { + if (rhs.hasTag(JCTree.Tag.LITERAL)) { JCLiteral l = (JCLiteral) rhs; return (String) l.value; } + } else if (e.hasTag(JCTree.Tag.LITERAL)) { + JCLiteral l = (JCLiteral) e; + return (String) l.value; } throw new IllegalArgumentException(e.toString()); } diff --git a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out b/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out deleted file mode 100644 index eecd7f7e638..00000000000 --- a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out +++ /dev/null @@ -1,61 +0,0 @@ -BasicTest.java:47:27: compiler.err.illegal.start.of.type -BasicTest.java:47:28: compiler.err.expected: '{' -BasicTest.java:47:36: compiler.err.expected: token.identifier -BasicTest.java:47:38: compiler.err.illegal.start.of.type -BasicTest.java:47:45: compiler.err.expected: token.identifier -BasicTest.java:47:47: compiler.err.expected: ';' -BasicTest.java:47:62: compiler.err.expected: token.identifier -BasicTest.java:47:84: compiler.err.expected: token.identifier -BasicTest.java:52:22: compiler.err.illegal.start.of.expr -BasicTest.java:52:31: compiler.err.expected: ';' -BasicTest.java:52:37: compiler.err.expected: token.identifier -BasicTest.java:53:30: compiler.err.expected: token.identifier -BasicTest.java:53:31: compiler.err.expected: -> -BasicTest.java:56:23: compiler.err.expected: token.identifier -BasicTest.java:56:24: compiler.err.expected2: '(', '[' -BasicTest.java:56:25: compiler.err.expected: ';' -BasicTest.java:56:27: compiler.err.invalid.meth.decl.ret.type.req -BasicTest.java:56:34: compiler.err.illegal.start.of.type -BasicTest.java:58:34: compiler.err.illegal.start.of.type -BasicTest.java:61:16: compiler.err.illegal.start.of.type -BasicTest.java:61:18: compiler.err.expected: ';' -BasicTest.java:61:24: compiler.err.illegal.start.of.type -BasicTest.java:61:26: compiler.err.expected: ';' -BasicTest.java:61:33: compiler.err.expected: token.identifier -BasicTest.java:61:34: compiler.err.illegal.start.of.type -BasicTest.java:61:35: compiler.err.expected: token.identifier -BasicTest.java:61:37: compiler.err.expected: ';' -BasicTest.java:61:45: compiler.err.expected: token.identifier -BasicTest.java:61:50: compiler.err.expected: token.identifier -BasicTest.java:62:16: compiler.err.expected: token.identifier -BasicTest.java:62:17: compiler.err.expected2: '(', '[' -BasicTest.java:62:18: compiler.err.expected: ';' -BasicTest.java:62:28: compiler.err.illegal.start.of.type -BasicTest.java:62:30: compiler.err.expected: ';' -BasicTest.java:62:36: compiler.err.illegal.start.of.type -BasicTest.java:62:38: compiler.err.expected: ';' -BasicTest.java:62:45: compiler.err.expected: token.identifier -BasicTest.java:62:46: compiler.err.illegal.start.of.type -BasicTest.java:62:47: compiler.err.expected: token.identifier -BasicTest.java:62:49: compiler.err.expected: ';' -BasicTest.java:62:57: compiler.err.expected: token.identifier -BasicTest.java:62:58: compiler.err.illegal.start.of.type -BasicTest.java:62:59: compiler.err.expected: token.identifier -BasicTest.java:64:25: compiler.err.illegal.start.of.type -BasicTest.java:64:27: compiler.err.expected: ';' -BasicTest.java:64:34: compiler.err.expected: token.identifier -BasicTest.java:64:38: compiler.err.expected: token.identifier -BasicTest.java:64:41: compiler.err.illegal.start.of.expr -BasicTest.java:64:50: compiler.err.expected: ';' -BasicTest.java:64:56: compiler.err.expected: token.identifier -BasicTest.java:69:17: compiler.err.expected: ';' -BasicTest.java:69:24: compiler.err.illegal.start.of.type -BasicTest.java:69:30: compiler.err.expected: ';' -BasicTest.java:69:59: compiler.err.expected: token.identifier -BasicTest.java:69:74: compiler.err.expected: ';' -BasicTest.java:74:22: compiler.err.expected: token.identifier -BasicTest.java:74:24: compiler.err.expected: ';' -BasicTest.java:74:25: compiler.err.illegal.start.of.type -BasicTest.java:74:33: compiler.err.expected: ';' -BasicTest.java:77:2: compiler.err.premature.eof -60 errors diff --git a/langtools/test/tools/javac/varargs/7042566/T7042566.java b/langtools/test/tools/javac/varargs/7042566/T7042566.java index 2f94c440c2e..6ef014c751e 100644 --- a/langtools/test/tools/javac/varargs/7042566/T7042566.java +++ b/langtools/test/tools/javac/varargs/7042566/T7042566.java @@ -23,13 +23,17 @@ /* * @test - * @bug 7042566 + * @bug 7042566 8006694 * @summary Unambiguous varargs method calls flagged as ambiguous + * temporarily workaround combo tests are causing time out in several platforms * @library ../../lib * @build JavacTestingAbstractThreadedTest - * @run main T7042566 + * @run main/othervm T7042566 */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.io.File; import java.net.URI; import java.util.Arrays; diff --git a/langtools/test/tools/javac/varargs/warning/Warn4.java b/langtools/test/tools/javac/varargs/warning/Warn4.java index 47b4ce39910..1a068c74244 100644 --- a/langtools/test/tools/javac/varargs/warning/Warn4.java +++ b/langtools/test/tools/javac/varargs/warning/Warn4.java @@ -23,14 +23,18 @@ /** * @test - * @bug 6945418 6993978 + * @bug 6945418 6993978 8006694 * @summary Project Coin: Simplified Varargs Method Invocation + * temporarily workaround combo tests are causing time out in several platforms * @author mcimadamore * @library ../../lib * @build JavacTestingAbstractThreadedTest - * @run main Warn4 + * @run main/othervm Warn4 */ +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) +// see JDK-8006746 + import java.net.URI; import java.util.Arrays; import java.util.Set; @@ -238,7 +242,6 @@ public class Warn4 for (Warning wkind : Warning.values()) { boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel, suppressLevelClient, suppressLevelDecl, modKind); - System.out.println("SUPPRESSED = " + isSuppressed); badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) != diagChecker.warnings.contains(wkind); } diff --git a/langtools/test/tools/javac/varargs/warning/Warn5.java b/langtools/test/tools/javac/varargs/warning/Warn5.java index 51d54940d18..e45cd361637 100644 --- a/langtools/test/tools/javac/varargs/warning/Warn5.java +++ b/langtools/test/tools/javac/varargs/warning/Warn5.java @@ -23,13 +23,18 @@ /** * @test - * @bug 6993978 7097436 + * @bug 6993978 7097436 8006694 * @summary Project Coin: Annotation to reduce varargs warnings + * temporarily workaround combo tests are causing time out in several platforms * @author mcimadamore * @library ../../lib * @build JavacTestingAbstractThreadedTest - * @run main Warn5 + * @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.util.EnumSet; diff --git a/langtools/test/tools/javadoc/6958836/Test.java b/langtools/test/tools/javadoc/6958836/Test.java index 75222700a98..41746f71347 100644 --- a/langtools/test/tools/javadoc/6958836/Test.java +++ b/langtools/test/tools/javadoc/6958836/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -61,6 +61,7 @@ public class Test { // Force en_US locale in lieu of something like -XDrawDiagnostics. // For some reason, this must be the first option when used. opts.addAll(list("-locale", "en_US")); + opts.add("-Xdoclint:none"); opts.addAll(list("-classpath", System.getProperty("test.src"))); opts.addAll(list("-d", testOutDir.getPath())); opts.addAll(testOpts); diff --git a/langtools/test/tools/javadoc/6964914/Test.java b/langtools/test/tools/javadoc/6964914/Test.java index 92362afc1f7..751f29572e9 100644 --- a/langtools/test/tools/javadoc/6964914/Test.java +++ b/langtools/test/tools/javadoc/6964914/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -45,6 +45,7 @@ public class Test { void javadoc(String path, String expect) { File testSrc = new File(System.getProperty("test.src")); String[] args = { + "-Xdoclint:none", "-source", "1.4", // enables certain Parser warnings "-bootclasspath", System.getProperty("sun.boot.class.path"), "-classpath", ".", diff --git a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java index 9714557571c..ce6a39f77c9 100644 --- a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java +++ b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -57,6 +57,7 @@ public class TestStdDoclet { Process p = new ProcessBuilder() .command(javadoc.getPath(), "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"), + "-Xdoclint:none", "-package", new File(testSrc, thisClassName + ".java").getPath()) .redirectErrorStream(true) diff --git a/langtools/test/tools/javadoc/MaxWarns.java b/langtools/test/tools/javadoc/MaxWarns.java index 9cd3b381c01..93b870f62d3 100644 --- a/langtools/test/tools/javadoc/MaxWarns.java +++ b/langtools/test/tools/javadoc/MaxWarns.java @@ -74,7 +74,7 @@ public class MaxWarns { String javadoc(File f) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - String[] args = { "-d", "api", f.getPath() }; + String[] args = { "-Xdoclint:none", "-d", "api", f.getPath() }; int rc = com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw, com.sun.tools.doclets.standard.Standard.class.getName(), args); pw.flush(); diff --git a/langtools/test/tools/javadoc/T6551367.java b/langtools/test/tools/javadoc/T6551367.java index 04e6bdc1bde..f82e7caa633 100644 --- a/langtools/test/tools/javadoc/T6551367.java +++ b/langtools/test/tools/javadoc/T6551367.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -46,7 +46,7 @@ public class T6551367 extends com.sun.tools.doclets.standard.Standard { File source = new File(testSrc, file); int rc = execute("javadoc", "T6551367", T6551367.class.getClassLoader(), - new String[]{source.getPath(), "-d", destDir.getAbsolutePath()}); + new String[]{"-Xdoclint:none", source.getPath(), "-d", destDir.getAbsolutePath()}); if (rc != 0) throw new Error("unexpected exit from javadoc: " + rc); } diff --git a/langtools/test/tools/javadoc/api/basic/RunTest.java b/langtools/test/tools/javadoc/api/basic/RunTest.java index 2e6c65252df..380f5b69a9d 100644 --- a/langtools/test/tools/javadoc/api/basic/RunTest.java +++ b/langtools/test/tools/javadoc/api/basic/RunTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6493690 + * @bug 6493690 8007490 * @summary javadoc should have a javax.tools.Tool service provider * @build APITest * @run main RunTest @@ -31,6 +31,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.PrintStream; import javax.tools.DocumentationTool; import javax.tools.ToolProvider; @@ -46,7 +47,7 @@ public class RunTest extends APITest { * Verify that run method can be invoked. */ @Test - public void testRun() throws Exception { + public void testRunOK() throws Exception { File testSrc = new File(System.getProperty("test.src")); File srcFile = new File(testSrc, "pkg/C.java"); File outDir = getOutDir(); @@ -77,7 +78,7 @@ public class RunTest extends APITest { * Verify that run method can be invoked. */ @Test - public void testRun2() throws Exception { + public void testRunFail() throws Exception { File outDir = getOutDir(); String badfile = "badfile.java"; String[] args = { "-d", outDir.getPath(), badfile }; @@ -100,5 +101,48 @@ public class RunTest extends APITest { } } + /** + * Verify that null args are accepted. + */ + @Test + public void testNullArgs() throws Exception { + File testSrc = new File(System.getProperty("test.src")); + File srcFile = new File(testSrc, "pkg/C.java"); + File outDir = getOutDir(); + String[] args = { "-d", outDir.getPath(), srcFile.getPath() }; + + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + PrintStream prevStdout = System.out; + System.setOut(new PrintStream(stdout)); + + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + PrintStream prevStderr = System.err; + System.setErr(new PrintStream(stderr)); + + int rc ; + try { + DocumentationTool tool = ToolProvider.getSystemDocumentationTool(); + rc = tool.run(null, null, null, args); + } finally { + System.setOut(prevStdout); + System.setErr(prevStderr); + } + + System.err.println("stdout >>" + stdout.toString() + "<<"); + System.err.println("stderr >>" + stderr.toString() + "<<"); + + if (rc == 0) { + System.err.println("call succeeded"); + checkFiles(outDir, standardExpectFiles); + String out = stdout.toString(); + for (String f: standardExpectFiles) { + String f1 = f.replace('/', File.separatorChar); + if (f1.endsWith(".html") && !out.contains(f1)) + error("expected string not found: " + f1); + } + } else { + error("call failed"); + } + } } diff --git a/langtools/test/tools/javadoc/doclint/DocLintTest.java b/langtools/test/tools/javadoc/doclint/DocLintTest.java new file mode 100644 index 00000000000..22557fa1f1f --- /dev/null +++ b/langtools/test/tools/javadoc/doclint/DocLintTest.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2012, 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. + */ + +/* + * @test + * @bug 8004834 + * @summary Add doclint support into javadoc + */ + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.tools.Diagnostic; +import javax.tools.DocumentationTool; +import javax.tools.DocumentationTool.DocumentationTask; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import static javax.tools.Diagnostic.Kind.*; + +import com.sun.tools.javac.main.Main; + +public class DocLintTest { + public static void main(String... args) throws Exception { + new DocLintTest().run(); + } + + DocumentationTool javadoc; + StandardJavaFileManager fm; + JavaFileObject file; + + final String code = + /* 01 */ "/** Class comment. */\n" + + /* 02 */ "public class Test {\n" + + /* 03 */ " /** Method comment. */\n" + + /* 04 */ " public void method() { }\n" + + /* 05 */ "\n" + + /* 06 */ " /** Syntax < error. */\n" + + /* 07 */ " private void syntaxError() { }\n" + + /* 08 */ "\n" + + /* 09 */ " /** @see DoesNotExist */\n" + + /* 10 */ " protected void referenceError() { }\n" + + /* 11 */ "\n" + + /* 12 */ " /** @return */\n" + + /* 13 */ " public int emptyReturn() { return 0; }\n" + + /* 14 */ "}\n"; + + private final String rawDiags = "-XDrawDiagnostics"; + + private enum Message { + // doclint messages + DL_ERR6(ERROR, "Test.java:6:16: compiler.err.proc.messager: malformed HTML"), + DL_ERR9(ERROR, "Test.java:9:14: compiler.err.proc.messager: reference not found"), + DL_WRN12(WARNING, "Test.java:12:9: compiler.warn.proc.messager: no description for @return"), + + // doclint messages when -XDrawDiagnostics is not in effect + DL_ERR9A(ERROR, "Test.java:9: error: reference not found"), + DL_WRN12A(WARNING, "Test.java:12: warning: no description for @return"), + + // javadoc messages about bad content: these should only appear when doclint is disabled + JD_WRN10(WARNING, "Test.java:10: warning - Tag @see: reference not found: DoesNotExist"), + JD_WRN13(WARNING, "Test.java:13: warning - @return tag has no arguments."), + + // javadoc messages for bad options + OPT_BADARG(ERROR, "javadoc: error - Invalid argument for -Xdoclint option"), + OPT_BADQUAL(ERROR, "javadoc: error - Access qualifiers not permitted for -Xdoclint arguments"); + + final Diagnostic.Kind kind; + final String text; + + static Message get(String text) { + for (Message m: values()) { + if (m.text.equals(text)) + return m; + } + return null; + } + + Message(Diagnostic.Kind kind, String text) { + this.kind = kind; + this.text = text; + } + + @Override + public String toString() { + return "[" + kind + ",\"" + text + "\"]"; + } + } + + void run() throws Exception { + javadoc = ToolProvider.getSystemDocumentationTool(); + fm = javadoc.getStandardFileManager(null, null, null); + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File("."))); + file = new SimpleJavaFileObject(URI.create("Test.java"), JavaFileObject.Kind.SOURCE) { + @Override + public CharSequence getCharContent(boolean ignoreEncoding) { + return code; + } + }; + + test(Collections.emptyList(), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR9A, Message.DL_WRN12A)); + + test(Arrays.asList(rawDiags), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR9, Message.DL_WRN12)); + + test(Arrays.asList("-Xdoclint:none"), + Main.Result.OK, + EnumSet.of(Message.JD_WRN10, Message.JD_WRN13)); + + test(Arrays.asList(rawDiags, "-Xdoclint"), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR9, Message.DL_WRN12)); + + test(Arrays.asList(rawDiags, "-Xdoclint:all/public"), + Main.Result.ERROR, + EnumSet.of(Message.OPT_BADQUAL)); + + test(Arrays.asList(rawDiags, "-Xdoclint:all", "-public"), + Main.Result.OK, + EnumSet.of(Message.DL_WRN12)); + + test(Arrays.asList(rawDiags, "-Xdoclint:syntax"), + Main.Result.OK, + EnumSet.of(Message.DL_WRN12)); + + test(Arrays.asList(rawDiags, "-Xdoclint:syntax", "-private"), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR6, Message.DL_WRN12)); + + test(Arrays.asList(rawDiags, "-Xdoclint:reference"), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR9)); + + test(Arrays.asList(rawDiags, "-Xdoclint:badarg"), + Main.Result.ERROR, + EnumSet.of(Message.OPT_BADARG)); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void test(List opts, Main.Result expectResult, Set expectMessages) { + System.err.println("test: " + opts); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + List files = Arrays.asList(file); + try { + DocumentationTask t = javadoc.getTask(pw, fm, null, null, opts, files); + boolean ok = t.call(); + pw.close(); + String out = sw.toString().replaceAll("[\r\n]+", "\n"); + if (!out.isEmpty()) + System.err.println(out); + if (ok && expectResult != Main.Result.OK) { + error("Compilation succeeded unexpectedly"); + } else if (!ok && expectResult != Main.Result.ERROR) { + error("Compilation failed unexpectedly"); + } else + check(out, expectMessages); + } catch (IllegalArgumentException e) { + System.err.println(e); + String expectOut = expectMessages.iterator().next().text; + if (expectResult != Main.Result.CMDERR) + error("unexpected exception caught"); + else if (!e.getMessage().equals(expectOut)) { + error("unexpected exception message: " + + e.getMessage() + + " expected: " + expectOut); + } + } + +// if (errors > 0) +// throw new Error("stop"); + } + + private void check(String out, Set expect) { + Pattern ignore = Pattern.compile("^(Building|Constructing|Generating|Loading|Standard|Starting| ) .*"); + Pattern stats = Pattern.compile("^([1-9]+) (error|warning)(s?)"); + Set found = EnumSet.noneOf(Message.class); + int e = 0, w = 0; + for (String line: out.split("[\r\n]+")) { + if (ignore.matcher(line).matches()) + continue; + + Matcher s = stats.matcher(line); + if (s.matches()) { + int i = Integer.valueOf(s.group(1)); + if (s.group(2).equals("error")) + e++; + else + w++; + continue; + } + + Message m = Message.get(line); + if (m == null) + error("Unexpected line: " + line); + else + found.add(m); + } + for (Message m: expect) { + if (!found.contains(m)) + error("expected message not found: " + m.text); + } + for (Message m: found) { + if (!expect.contains(m)) + error("unexpected message found: " + m.text); + } + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; +} diff --git a/langtools/test/tools/javap/typeAnnotations/JSR175Annotations.java b/langtools/test/tools/javap/typeAnnotations/JSR175Annotations.java new file mode 100644 index 00000000000..3504cb520bb --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/JSR175Annotations.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.*; +import com.sun.tools.classfile.*; + +/* + * @test JSR175Annotations + * @bug 6843077 + * @summary test that only type annotations are recorded as such in classfile + */ + +public class JSR175Annotations { + public static void main(String[] args) throws Exception { + new JSR175Annotations().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.*;"); + out.println("abstract class Test { "); + out.println(" @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})"); + out.println(" @Retention(RetentionPolicy.RUNTIME)"); + out.println(" @interface A { }"); + out.println(" @A String m;"); + out.println(" @A String method(@A String a) {"); + out.println(" return a;"); + out.println(" }"); + out.println("}"); + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 0; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/NewArray.java b/langtools/test/tools/javap/typeAnnotations/NewArray.java new file mode 100644 index 00000000000..bcb25efc047 --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/NewArray.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.*; +import com.sun.tools.classfile.*; + +/* + * @test NewArray + * @bug 6843077 + * @summary test that all type annotations are present in the classfile + */ + +public class NewArray { + public static void main(String[] args) throws Exception { + new NewArray().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.*;"); + out.println("import java.util.*;"); + out.println("class Test { "); + out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println(" @interface A { }"); + + out.println(" void test() {"); + out.println(" Object a = new @A String @A [5] @A [];"); + out.println(" Object b = new @A String @A [5] @A [3];"); + out.println(" Object c = new @A String @A [] @A [] {};"); + out.println(" }"); + out.println("}"); + + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 9; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/Presence.java b/langtools/test/tools/javap/typeAnnotations/Presence.java new file mode 100644 index 00000000000..6ed86083eb8 --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/Presence.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.*; +import java.lang.annotation.ElementType; + +import com.sun.tools.classfile.*; + +/* + * @test Presence + * @bug 6843077 + * @summary test that all type annotations are present in the classfile + */ + +public class Presence { + public static void main(String[] args) throws Exception { + new Presence().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.util.*;"); + out.println("import java.lang.annotation.*;"); + + out.println("class Test<@Test.A T extends @Test.A List<@Test.A String>> { "); + out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println(" @interface A { }"); + + out.println(" Map<@A String, Map<@A String, @A String>> f1;"); + + out.println(" <@A TM extends @A List<@A String>>"); + out.println(" Map<@A String, @A List<@A String>>"); + out.println(" method(@A Test this, List<@A String> @A [] param1, String @A [] @A ... param2)"); + out.println(" throws @A Exception {"); + out.println(" @A String lc1 = null;"); + out.println(" @A List<@A String> lc2 = null;"); + out.println(" @A String @A [] [] @A[] lc3 = null;"); + out.println(" List> lc4 = null;"); + out.println(" Object lc5 = (@A List<@A String>) null;"); + out.println(" boolean lc6 = lc1 instanceof @A String;"); + out.println(" boolean lc7 = lc5 instanceof @A String @A [] @A [];"); + out.println(" new @A ArrayList<@A String>();"); + out.println(" Object lc8 = new @A String @A [4];"); + out.println(" try {"); + out.println(" Object lc10 = int.class;"); + out.println(" } catch (@A Exception e) { e.toString(); }"); + out.println(" return null;"); + out.println(" }"); + out.println(" void vararg1(String @A ... t) { } "); + out.println("}"); + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 38; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/PresenceInner.java b/langtools/test/tools/javap/typeAnnotations/PresenceInner.java new file mode 100644 index 00000000000..1b859206a3d --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/PresenceInner.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2009, 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.*; +import com.sun.tools.classfile.*; + +/* + * @test PresenceInner + * @bug 6843077 + * @summary test that annotations in inner types count only once + */ + +public class PresenceInner { + public static void main(String[] args) throws Exception { + new PresenceInner().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + // counts are zero when vising outer class + countAnnotations(0); + + // visit inner class + File innerFile = new File("Test$1Inner.class"); + ClassFile icf = ClassFile.read(innerFile); + test(icf); + for (Field f : icf.fields) { + test(cf, f); + } + for (Method m: icf.methods) { + test(cf, m); + } + + countAnnotations(1); + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + + out.println("import java.lang.annotation.*;"); + out.println("class Test {"); + out.println(" void method() {"); + out.println(" class Inner { }"); + out.println(" }"); + out.println("}"); + out.println("@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println("@interface A { }"); + out.close(); + System.out.println(f.getAbsolutePath()); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations(int expected_invisibles) { + int expected_visibles = 0; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/T6855990.java b/langtools/test/tools/javap/typeAnnotations/T6855990.java new file mode 100644 index 00000000000..bc24eda6f11 --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/T6855990.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009, 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.*; + +/* + * @test + * @bug 6855990 + * @summary InstructionDetailWriter should support new 308 annotations attribute + */ + +public class T6855990 { + public static void main(String[] args) throws Exception { + new T6855990().run(); + } + + public void run() throws Exception { + @Simple String[] args = { "-c", "-XDdetails:typeAnnotations", "T6855990" }; + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javap.Main.run(args, pw); + pw.close(); + String out = sw.toString(); + System.out.println(out); + if (out.indexOf("@Simple: LOCAL_VARIABLE") == -1) + throw new Exception("expected output not found"); + } +} + +@interface Simple { } + diff --git a/langtools/test/tools/javap/typeAnnotations/TypeCasts.java b/langtools/test/tools/javap/typeAnnotations/TypeCasts.java new file mode 100644 index 00000000000..589b91fa13e --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/TypeCasts.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2009, 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.*; +import com.sun.tools.classfile.*; + +/* + * @test + * @bug 6843077 + * @summary test that typecasts annotation are emitted if only the cast + * expression is optimized away + */ + +public class TypeCasts { + public static void main(String[] args) throws Exception { + new TypeCasts().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.*;"); + out.println("class Test { "); + out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println(" @interface A { }"); + + out.println(" void emit() {"); + out.println(" Object o = null;"); + out.println(" String s = null;"); + + out.println(" String a0 = (@A String)o;"); + out.println(" Object a1 = (@A Object)o;"); + + out.println(" String b0 = (@A String)s;"); + out.println(" Object b1 = (@A Object)s;"); + out.println(" }"); + + out.println(" void alldeadcode() {"); + out.println(" Object o = null;"); + + out.println(" if (false) {"); + out.println(" String a0 = (@A String)o;"); + out.println(" }"); + out.println(" }"); + + out.println("}"); + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 4; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/Visibility.java b/langtools/test/tools/javap/typeAnnotations/Visibility.java new file mode 100644 index 00000000000..9fe348bad6c --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/Visibility.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.*; +import com.sun.tools.classfile.*; + +/* + * @test Visibility + * @bug 6843077 + * @summary test that type annotations are recorded in the classfile + */ + +public class Visibility { + public static void main(String[] args) throws Exception { + new Visibility().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.ElementType;"); + out.println("import java.lang.annotation.Retention;"); + out.println("import java.lang.annotation.RetentionPolicy;"); + out.println("import java.lang.annotation.Target;"); + out.println("abstract class Test { "); + // visible annotations: RUNTIME + out.println(" @Retention(RetentionPolicy.RUNTIME)"); + out.println(" @Target(ElementType.TYPE_USE)"); + out.println(" @interface A { }"); + out.println(" void visible(@A Test this) { }"); + + // invisible annotations: CLASS + out.println(" @Retention(RetentionPolicy.CLASS)"); + out.println(" @Target(ElementType.TYPE_USE)"); + out.println(" @interface B { }"); + out.println(" void invisible(@B Test this) { }"); + + // source annotations + out.println(" @Retention(RetentionPolicy.SOURCE)"); + out.println(" @Target(ElementType.TYPE_USE)"); + out.println(" @interface C { }"); + out.println(" void source(@C Test this) { }"); + + // default visibility: CLASS + out.println(" @Target(ElementType.TYPE_USE)"); + out.println(" @interface D { }"); + out.println(" void def(@D Test this) { }"); + out.println("}"); + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_all = 3, expected_visibles = 1, expected_invisibles = 2; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/javap/typeAnnotations/Wildcards.java b/langtools/test/tools/javap/typeAnnotations/Wildcards.java new file mode 100644 index 00000000000..7e011b260d3 --- /dev/null +++ b/langtools/test/tools/javap/typeAnnotations/Wildcards.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2009, 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.*; +import com.sun.tools.classfile.*; + +/* + * @test Wildcards + * @bug 6843077 + * @summary test that annotations target wildcards get emitted to classfile + */ +public class Wildcards { + public static void main(String[] args) throws Exception { + new Wildcards().run(); + } + + public void run() throws Exception { + File javaFile = writeTestFile(); + File classFile = compileTestFile(javaFile); + + ClassFile cf = ClassFile.read(classFile); + test(cf); + for (Field f : cf.fields) { + test(cf, f); + } + for (Method m: cf.methods) { + test(cf, m); + } + + countAnnotations(); + + if (errors > 0) + throw new Exception(errors + " errors found"); + System.out.println("PASSED"); + } + + void test(ClassFile cf) { + test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Method m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + void test(ClassFile cf, Field m) { + test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); + test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, String name, boolean visible) { + int index = cf.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = cf.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Method m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + // test the result of Attributes.getIndex according to expectations + // encoded in the method's name + void test(ClassFile cf, Field m, String name, boolean visible) { + int index = m.attributes.getIndex(cf.constant_pool, name); + if (index != -1) { + Attribute attr = m.attributes.get(index); + assert attr instanceof RuntimeTypeAnnotations_attribute; + RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; + all += tAttr.annotations.length; + if (visible) + visibles += tAttr.annotations.length; + else + invisibles += tAttr.annotations.length; + } + } + + File writeTestFile() throws IOException { + File f = new File("Test.java"); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println("import java.lang.annotation.*;"); + out.println("import java.util.*;"); + out.println("class Test { "); + out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); + out.println(" @interface A { }"); + + out.println(" List f;"); + + out.println(" List test(List p) {"); + out.println(" List l;"); // not counted... gets optimized away + out.println(" return null;"); + out.println(" }"); + out.println("}"); + + out.close(); + return f; + } + + File compileTestFile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + void countAnnotations() { + int expected_visibles = 0, expected_invisibles = 3; + int expected_all = expected_visibles + expected_invisibles; + + if (expected_all != all) { + errors++; + System.err.println("expected " + expected_all + + " annotations but found " + all); + } + + if (expected_visibles != visibles) { + errors++; + System.err.println("expected " + expected_visibles + + " visibles annotations but found " + visibles); + } + + if (expected_invisibles != invisibles) { + errors++; + System.err.println("expected " + expected_invisibles + + " invisibles annotations but found " + invisibles); + } + + } + + int errors; + int all; + int visibles; + int invisibles; +} diff --git a/langtools/test/tools/sjavac/SJavac.java b/langtools/test/tools/sjavac/SJavac.java new file mode 100644 index 00000000000..1c8d61216a6 --- /dev/null +++ b/langtools/test/tools/sjavac/SJavac.java @@ -0,0 +1,573 @@ +/* + * Copyright (c) 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.util.*; +import java.io.*; +import java.net.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.charset.*; + +import com.sun.tools.sjavac.Main; + +public +class SJavac { + + public static void main(String... args) throws Exception { + SJavac s = new SJavac(); + s.test(); + } + + FileSystem defaultfs = FileSystems.getDefault(); + + // Where to put generated sources that will + // test aspects of sjavac, ie JTWork/scratch/gensrc + Path gensrc; + // More gensrc dirs are used to test merging of serveral source roots. + Path gensrc2; + Path gensrc3; + + // Where to put compiled classes. + Path bin; + // Where to put c-header files. + Path headers; + + // The sjavac compiler. + Main main = new Main(); + + // Remember the previous bin and headers state here. + Map previous_bin_state; + Map previous_headers_state; + + public void test() throws Exception { + gensrc = defaultfs.getPath("gensrc"); + gensrc2 = defaultfs.getPath("gensrc2"); + gensrc3 = defaultfs.getPath("gensrc3"); + bin = defaultfs.getPath("bin"); + headers = defaultfs.getPath("headers"); + + Files.createDirectory(gensrc); + Files.createDirectory(gensrc2); + Files.createDirectory(gensrc3); + Files.createDirectory(bin); + Files.createDirectory(headers); + + initialCompile(); + incrementalCompileNoChanges(); + incrementalCompileDroppingClasses(); + incrementalCompileWithChange(); + incrementalCompileDropAllNatives(); + incrementalCompileAddNative(); + incrementalCompileChangeNative(); + compileWithOverrideSource(); + compileWithInvisibleSources(); + compileCircularSources(); + + delete(gensrc); + delete(gensrc2); + delete(gensrc3); + delete(bin); + } + + void initialCompile() throws Exception { + System.out.println("\nInitial compile of gensrc."); + System.out.println("----------------------------"); + populate(gensrc, + "alfa/AINT.java", + "package alfa; public interface AINT { void aint(); }", + + "alfa/A.java", + "package alfa; public class A implements AINT { "+ + "public final static int DEFINITION = 17; public void aint() { } }", + + "alfa/AA.java", + "package alfa;"+ + "// A package private class, not contributing to the public api.\n"+ + "class AA {"+ + " // A properly nested static inner class.\n"+ + " static class AAA { }\n"+ + " // A properly nested inner class.\n"+ + " class AAAA { }\n"+ + " Runnable foo() {\n"+ + " // A proper anonymous class.\n"+ + " return new Runnable() { public void run() { } };\n"+ + " }\n"+ + " AAA aaa;\n"+ + " AAAA aaaa;\n"+ + " AAAAA aaaaa;\n"+ + "}\n"+ + "class AAAAA {\n"+ + " // A bad auxiliary class, but no one is referencing it\n"+ + " // from outside of this source file, therefore it is ok.\n"+ + "}\n", + + "beta/BINT.java", + "package beta;public interface BINT { void foo(); }", + + "beta/B.java", + "package beta; import alfa.A; public class B {"+ + "private int b() { return A.DEFINITION; } native void foo(); }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false", "--log=debug"); + previous_bin_state = collectState(bin); + previous_headers_state = collectState(headers); + } + + void incrementalCompileNoChanges() throws Exception { + System.out.println("\nTesting that no change in sources implies no change in binaries."); + System.out.println("------------------------------------------------------------------"); + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false", "--log=debug"); + Map new_bin_state = collectState(bin); + verifyEqual(new_bin_state, previous_bin_state); + Map new_headers_state = collectState(headers); + verifyEqual(previous_headers_state, new_headers_state); + } + + void incrementalCompileDroppingClasses() throws Exception { + System.out.println("\nTesting that deleting AA.java deletes all"); + System.out.println("generated inner class as well as AA.class"); + System.out.println("-----------------------------------------"); + removeFrom(gensrc, "alfa/AA.java"); + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false", "--log=debug"); + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenRemoved(previous_bin_state, new_bin_state, + "bin/alfa/AA$1.class", + "bin/alfa/AA$AAAA.class", + "bin/alfa/AA$AAA.class", + "bin/alfa/AAAAA.class", + "bin/alfa/AA.class"); + + previous_bin_state = new_bin_state; + Map new_headers_state = collectState(headers); + verifyEqual(previous_headers_state, new_headers_state); + } + + void incrementalCompileWithChange() throws Exception { + System.out.println("\nNow update the A.java file with a new timestamps and"); + System.out.println("new final static definition. This should trigger a recompile,"); + System.out.println("not only of alfa, but also beta."); + System.out.println("But check that the generated native header was not updated!"); + System.out.println("Since we did not modify the native api of B."); + System.out.println("-------------------------------------------------------------"); + + populate(gensrc,"alfa/A.java", + "package alfa; public class A implements AINT { "+ + "public final static int DEFINITION = 18; public void aint() { } private void foo() { } }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false", "--log=debug"); + Map new_bin_state = collectState(bin); + + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/alfa/A.class", + "bin/alfa/AINT.class", + "bin/beta/B.class", + "bin/beta/BINT.class", + "bin/javac_state"); + previous_bin_state = new_bin_state; + + Map new_headers_state = collectState(headers); + verifyEqual(new_headers_state, previous_headers_state); + } + + void incrementalCompileDropAllNatives() throws Exception { + System.out.println("\nNow update the B.java file with one less native method,"); + System.out.println("ie it has no longer any methods!"); + System.out.println("Verify that beta_B.h is removed!"); + System.out.println("---------------------------------------------------------"); + + populate(gensrc,"beta/B.java", + "package beta; import alfa.A; public class B {"+ + "private int b() { return A.DEFINITION; } }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false", "--log=debug"); + Map new_bin_state = collectState(bin); + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/beta/B.class", + "bin/beta/BINT.class", + "bin/javac_state"); + previous_bin_state = new_bin_state; + + Map new_headers_state = collectState(headers); + verifyThatFilesHaveBeenRemoved(previous_headers_state, new_headers_state, + "headers/beta_B.h"); + previous_headers_state = new_headers_state; + } + + void incrementalCompileAddNative() throws Exception { + System.out.println("\nNow update the B.java file with a final static annotated with @Native."); + System.out.println("Verify that beta_B.h is added again!"); + System.out.println("------------------------------------------------------------------------"); + + populate(gensrc,"beta/B.java", + "package beta; import alfa.A; public class B {"+ + "private int b() { return A.DEFINITION; } "+ + "@java.lang.annotation.Native final static int alfa = 42; }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false", "--log=debug"); + Map new_bin_state = collectState(bin); + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/beta/B.class", + "bin/beta/BINT.class", + "bin/javac_state"); + previous_bin_state = new_bin_state; + + Map new_headers_state = collectState(headers); + verifyThatFilesHaveBeenAdded(previous_headers_state, new_headers_state, + "headers/beta_B.h"); + previous_headers_state = new_headers_state; + } + + void incrementalCompileChangeNative() throws Exception { + System.out.println("\nNow update the B.java file with a new value for the final static"+ + " annotated with @Native."); + System.out.println("Verify that beta_B.h is rewritten again!"); + System.out.println("-------------------------------------------------------------------"); + + populate(gensrc,"beta/B.java", + "package beta; import alfa.A; public class B {"+ + "private int b() { return A.DEFINITION; } "+ + "@java.lang.annotation.Native final static int alfa = 43; }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false", "--log=debug"); + Map new_bin_state = collectState(bin); + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/beta/B.class", + "bin/beta/BINT.class", + "bin/javac_state"); + previous_bin_state = new_bin_state; + + Map new_headers_state = collectState(headers); + verifyNewerFiles(previous_headers_state, new_headers_state, + "headers/beta_B.h"); + previous_headers_state = new_headers_state; + } + + void compileWithOverrideSource() throws Exception { + System.out.println("\nNow verify that we can override sources to be compiled."); + System.out.println("Compile gensrc and gensrc2. However do not compile broken beta.B in gensrc,"); + System.out.println("only compile ok beta.B in gensrc2."); + System.out.println("---------------------------------------------------------------------------"); + + delete(gensrc); + delete(gensrc2); + delete(bin); + previous_bin_state = collectState(bin); + + populate(gensrc,"alfa/A.java", + "package alfa; import beta.B; import gamma.C; public class A { B b; C c; }", + "beta/B.java", + "package beta; public class B { broken", + "gamma/C.java", + "package gamma; public class C { }"); + + populate(gensrc2, + "beta/B.java", + "package beta; public class B { }"); + + compile("-x", "beta", "gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false"); + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/A.class", + "bin/beta/B.class", + "bin/gamma/C.class", + "bin/javac_state"); + + System.out.println("----- Compile with exluded beta went well!"); + delete(bin); + compileExpectFailure("gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false"); + + System.out.println("----- Compile without exluded beta failed, as expected! Good!"); + delete(bin); + } + + void compileWithInvisibleSources() throws Exception { + System.out.println("\nNow verify that we can make sources invisible to linking (sourcepath)."); + System.out.println("Compile gensrc and link against gensrc2 and gensrc3, however"); + System.out.println("gensrc2 contains broken code in beta.B, thus we must exclude that package"); + System.out.println("fortunately gensrc3 contains a proper beta.B."); + System.out.println("------------------------------------------------------------------------"); + + // Start with a fresh gensrcs and bin. + delete(gensrc); + delete(gensrc2); + delete(gensrc3); + delete(bin); + previous_bin_state = collectState(bin); + + populate(gensrc,"alfa/A.java", + "package alfa; import beta.B; import gamma.C; public class A { B b; C c; }"); + populate(gensrc2,"beta/B.java", + "package beta; public class B { broken", + "gamma/C.java", + "package gamma; public class C { }"); + populate(gensrc3, "beta/B.java", + "package beta; public class B { }"); + + compile("gensrc", "-x", "beta", "-sourcepath", "gensrc2", + "-sourcepath", "gensrc3", "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false"); + + System.out.println("The first compile went well!"); + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/A.class", + "bin/javac_state"); + + System.out.println("----- Compile with exluded beta went well!"); + delete(bin); + compileExpectFailure("gensrc", "-sourcepath", "gensrc2", "-sourcepath", "gensrc3", + "-d", "bin", "-h", "headers", "-j", "1", + "--server:portfile=testserver,background=false"); + + System.out.println("----- Compile without exluded beta failed, as expected! Good!"); + delete(bin); + } + + void compileCircularSources() throws Exception { + System.out.println("\nNow verify that circular sources split on multiple cores can be compiled."); + System.out.println("---------------------------------------------------------------------------"); + + // Start with a fresh gensrcs and bin. + delete(gensrc); + delete(gensrc2); + delete(gensrc3); + delete(bin); + previous_bin_state = collectState(bin); + + populate(gensrc,"alfa/A.java", + "package alfa; public class A { beta.B b; }", + "beta/B.java", + "package beta; public class B { gamma.C c; }", + "gamma/C.java", + "package gamma; public class C { alfa.A a; }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "3", + "--server:portfile=testserver,background=false","--log=debug"); + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/A.class", + "bin/beta/B.class", + "bin/gamma/C.class", + "bin/javac_state"); + delete(bin); + } + + void removeFrom(Path dir, String... args) throws IOException { + for (String filename : args) { + Path p = dir.resolve(filename); + Files.delete(p); + } + } + + void populate(Path src, String... args) throws IOException { + if (!Files.exists(src)) { + Files.createDirectory(src); + } + String[] a = args; + for (int i = 0; i() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException + { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException + { + if (e == null) { + if (!dir.equals(root)) Files.delete(dir); + return FileVisitResult.CONTINUE; + } else { + // directory iteration failed + throw e; + } + } + }); + } + + void compile(String... args) throws Exception { + int rc = main.go(args, System.out, System.err); + if (rc != 0) throw new Exception("Error during compile!"); + + // Wait a second, to get around the (temporary) problem with + // second resolution in the Java file api. But do not do this + // on windows where the timestamps work. + long in_a_sec = System.currentTimeMillis()+1000; + while (in_a_sec > System.currentTimeMillis()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } + + void compileExpectFailure(String... args) throws Exception { + int rc = main.go(args, System.out, System.err); + if (rc == 0) throw new Exception("Expected error during compile! Did not fail!"); + } + + Map collectState(Path dir) throws IOException + { + final Map files = new HashMap<>(); + Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException + { + files.put(file.toString(),new Long(Files.getLastModifiedTime(file).toMillis())); + return FileVisitResult.CONTINUE; + } + }); + return files; + } + + void verifyThatFilesHaveBeenRemoved(Map from, + Map to, + String... args) throws Exception { + + Set froms = from.keySet(); + Set tos = to.keySet(); + + if (froms.equals(tos)) { + throw new Exception("Expected new state to have fewer files than previous state!"); + } + + for (String t : tos) { + if (!froms.contains(t)) { + throw new Exception("Expected "+t+" to exist in previous state!"); + } + } + + for (String f : args) { + f = f.replace("/", File.separator); + if (!froms.contains(f)) { + throw new Exception("Expected "+f+" to exist in previous state!"); + } + if (tos.contains(f)) { + throw new Exception("Expected "+f+" to have been removed from the new state!"); + } + } + + if (froms.size() - args.length != tos.size()) { + throw new Exception("There are more removed files than the expected list!"); + } + } + + void verifyThatFilesHaveBeenAdded(Map from, + Map to, + String... args) throws Exception { + + Set froms = from.keySet(); + Set tos = to.keySet(); + + if (froms.equals(tos)) { + throw new Exception("Expected new state to have more files than previous state!"); + } + + for (String t : froms) { + if (!tos.contains(t)) { + throw new Exception("Expected "+t+" to exist in new state!"); + } + } + + for (String f : args) { + f = f.replace("/", File.separator); + if (!tos.contains(f)) { + throw new Exception("Expected "+f+" to have been added to new state!"); + } + if (froms.contains(f)) { + throw new Exception("Expected "+f+" to not exist in previous state!"); + } + } + + if (froms.size() + args.length != tos.size()) { + throw new Exception("There are more added files than the expected list!"); + } + } + + void verifyNewerFiles(Map from, + Map to, + String... args) throws Exception { + if (!from.keySet().equals(to.keySet())) { + throw new Exception("Expected the set of files to be identical!"); + } + Set files = new HashSet(); + for (String s : args) { + files.add(s.replace("/", File.separator)); + } + for (String fn : from.keySet()) { + long f = from.get(fn); + long t = to.get(fn); + if (files.contains(fn)) { + if (t <= f) { + throw new Exception("Expected "+fn+" to have a more recent timestamp!"); + } + } else { + if (t != f) { + throw new Exception("Expected "+fn+" to have the same timestamp!"); + } + } + } + } + + String print(Map m) { + StringBuilder b = new StringBuilder(); + Set keys = m.keySet(); + for (String k : keys) { + b.append(k+" "+m.get(k)+"\n"); + } + return b.toString(); + } + + void verifyEqual(Map from, Map to) throws Exception { + if (!from.equals(to)) { + System.out.println("FROM---"+print(from)); + System.out.println("TO-----"+print(to)); + throw new Exception("The dir should not differ! But it does!"); + } + } +} diff --git a/langtools/test/tools/sjavac/SJavacWrapper.java b/langtools/test/tools/sjavac/SJavacWrapper.java new file mode 100644 index 00000000000..bba27eb7f62 --- /dev/null +++ b/langtools/test/tools/sjavac/SJavacWrapper.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 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. + */ + +/* + * @test + * @summary Test all aspects of sjavac. + * + * @bug 8004658 + * @summary Add internal smart javac wrapper to solve JEP 139 + * + * @run main SJavacWrapper + */ + +import java.io.*; +import java.lang.reflect.Method; +import java.net.*; + + +public +class SJavacWrapper { + + public static void main(String... args) throws Exception { + URL url = SJavacWrapper.class.getClassLoader().getResource("com/sun/tools/sjavac/Main.class"); + if (url == null) { + // No sjavac in the classpath. + System.out.println("sjavac not available: pass by default"); + return; + } + + File testSrc = new File(System.getProperty("test.src")); + File sjavac_java = new File(testSrc, "SJavac.java"); + File testClasses = new File(System.getProperty("test.classes")); + File sjavac_class = new File(testClasses, "SJavac.class"); + if (sjavac_class.lastModified() < sjavac_java.lastModified()) { + String[] javac_args = { "-d", testClasses.getPath(), sjavac_java.getPath() }; + System.err.println("Recompiling SJavac.java"); + int rc = com.sun.tools.javac.Main.compile(javac_args); + if (rc != 0) + throw new Exception("compilation failed"); + } + + Class sjavac = Class.forName("SJavac"); + Method sjavac_main = sjavac.getMethod("main", String[].class); + sjavac_main.invoke(null, new Object[] { args }); + } + +} diff --git a/make/jprt.properties b/make/jprt.properties index 990c442a164..b7bad856278 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -92,6 +92,7 @@ jprt.make.rule.core.test.targets= \ ${jprt.my.test.target.set:TESTNAME=jdk_text}, \ ${jprt.my.test.target.set:TESTNAME=jdk_tools}, \ ${jprt.my.test.target.set:TESTNAME=jdk_jfr}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_time}, \ ${jprt.my.test.target.set:TESTNAME=jdk_other} # All vm test targets (testset=all) diff --git a/test/Makefile b/test/Makefile index 9e4d509b550..701d39c4bfb 100644 --- a/test/Makefile +++ b/test/Makefile @@ -63,7 +63,8 @@ JDK_DEFAULT_TEST_LIST = \ jdk_nio \ jdk_security1 \ jdk_text \ - jdk_util + jdk_util \ + jdk_time # These tests are not part of the default testing list JDK_NONDEFAULT_TEST_LIST = \